QT入门之QMainWindow

QMainWindow

      • 1 简介
      • 2 Menu Bar
        • 2.1 简单示例
      • 3 状态栏
        • 3.1 示例
      • 4 工具栏
        • 4.1 简单示例
        • 4.3 设置方向和工具栏中组件的排列方向
        • 4.4 设置固定方向
        • 4.5 addToolBarBreak()
      • 5 setCentralWidget() 设置中心区域
      • 6 QDockWidget
        • 6.1 setFeatures()
      • 7 保存 / 设置窗口状态
        • 7.1 简单示例:
      • 8 完整代码

1 简介

在桌面程序中,任何软件都有界面,界面就是与用户交互的,一般体现为窗口。在 QT 中通过继承 QMainWindow 来实现自定义的窗口,并为我们规划好了一个窗口大致包含的几个部分:顶部的菜单栏、底部的状态栏、外圈环绕的工具栏、内圈环绕的可悬浮的窗口部件以及最中心的中心部件。如下图:
QT入门之QMainWindow_第1张图片

下面就依次介绍一下 QMainWindow 中各个组件的 UI 效果及作用,这里只是简单的介绍一下,让大家有个印象,后面的文章再逐个详细的介绍。

2 Menu Bar

菜单中栏中,

  • 可以添加多个菜单,但是菜单并不负责执行具体的操作而是在菜单中添加不同的 “动作”(QAction)来完成
  • 在菜单栏中除了添加菜单,还可以直接添加 QAction
2.1 简单示例

MainWindow.h :

class MainWindow : public QMainWindow
{
    Q_OBJECT

private slots:
    void newActTriggered();
    void operateActTriggered();

public:
    QMenuBar *mBar;//菜单栏
    QMenu *fileMenu;
    QMenu *editMenu;
    QAction *newAct;
    QAction *operateAct;
    MainWindow(QWidget *parent = 0);
    void createMenus();
};

MainWindow.cpp:
本段代码主要完成在菜单栏中:

  • 添加一个 “文件” 菜单,并在文件菜单中添加一个 “new” 菜单项
  • 添加一个 “编辑”菜单,但是给菜单没有菜单项
  • 添加一个 “操作” 动作。
#include "mainwindow.h"
#include "qdebug.h"
void MainWindow::createMenus()
  {
      mBar = menuBar();//获取菜单栏
      fileMenu = mBar->addMenu(tr("文件"));//创建文件菜单
      editMenu = mBar->addMenu(tr("编辑"));//创建编辑菜单
      //在菜单栏中添加一个 QAction 并指定 triggered() 信号的槽函数
      operateAct = mBar->addAction(tr("操作"),this,SLOT(operateActTriggered()));
	  //在文件菜单中添加 new 菜单子项
      newAct = new QAction("new");
      fileMenu->addAction(newAct);
	
      connect(this->newAct,SIGNAL(triggered()),this,SLOT(newActTriggered()));
}
//当 new 菜单子项被点击时执行
void MainWindow::newActTriggered(){
    qDebug()<<"newActTriggered()";
}
//当 操作 被点击时执行
void MainWindow::operateActTriggered(){
    qDebug()<<"operateTriggered()";
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    createMenus();
}

运行结果如下:
QT入门之QMainWindow_第2张图片
当我们点击 “new” 时就会在控制台输出:

newActTriggered()

当我们点击 “操作” 时就会在控制台输出:

operateTriggered()

我们除了可以通过 menuBar() 方法获取一个系统为我们创建好的 QMenuBar 对象外,我们也可以自己创建一个 QMenuBar 对象,再通过 setMenuBar() 将它设置到 MainWindow 中。

3 状态栏

一般的桌面软件,在窗口界面的左下角或者最下面都是有一个状态栏的,一般显示文本编辑器中此时光标的位置,或当前文件的名称等等。在 qt 中,我们也可以给 QMainWindow 设置状态栏。

3.1 示例
void MainWindow::createStatusBar(){
   sBar = statusBar();//获取窗口的状态栏对象 QStatusBar 实例。

   sBar->showMessage(tr("这里是状态栏"),0);//状态栏显示的文本
}

QT入门之QMainWindow_第3张图片

4 工具栏

一般软件中,工具栏也是由一些可点击的“动作”组成的,与菜单栏不同的是,工具栏一般都是些可点击的图标,在 UI 交互上,给用户一种更加直观的感觉。

我们看一下 NodePad++ 的界面做一个简单的认识:
QT入门之QMainWindow_第4张图片

4.1 简单示例

接下来我们就看一下如何用 QT 给窗口添加工具栏。

void MainWindow::showToolBar(){
    fileToolBar = addToolBar(tr("文件工具"));
    fileToolBar->addAction(newAct);
}

在这个案例中我们通过 QMainWindowaddToolBar() 方法向窗口中添加一个工具栏,然后再在窗口中添加了一个 QAction 。这个 newAct 是我们前面定义的,它一样可以被点击,并执行槽函数。

运行结果:这个我们的工具栏就是很简单的文字,大家可以给它添加一些有图标的QAction 就可以了。
QT入门之QMainWindow_第5张图片
并且现在这个工具栏我们可以随意拖动到窗口的下方、右方、左方。

QT入门之QMainWindow_第6张图片
这也就是为什么,在介绍 QMainWindow 的各个组件的时候,QToolBar 是占了一圈的原因,工具栏可以随意的放在四个方向。

4.3 设置方向和工具栏中组件的排列方向

我们可以通过 fileToolBar->setMovable(false); 方法将工具栏固定住,用户就不能随意拖动了
也可通过 fileToolBar->setOrientation(Qt::Horizontal); 方法设置工具栏中的各个组件为水平排列Qt::Vertical 为竖直方向

4.4 设置固定方向

通过 addToolBar(const QString &title); 默认是在上方的,且不能再设置位置了。可以通过addToolBar(Qt::ToolBarArea area, QToolBar *toolbar); 方法将一个工具栏添加到指定的位置上

	ediToolBar = new QToolBar(tr("操作工具"));
    ediToolBar->addAction(operateAct);
    ediToolBar->addAction(newAct);
    ediToolBar->setMovable(false);
    addToolBar(Qt::RightToolBarArea,ediToolBar);//添加到右边

QT入门之QMainWindow_第7张图片

4.5 addToolBarBreak()

addToolBarBreak(); 使工具栏之间添加一个间隔。

void MainWindow::showToolBar(){
    fileToolBar = addToolBar(tr("文件工具"));
    fileToolBar->setMovable(false);
    fileToolBar->addAction(newAct);

    addToolBarBreak(Qt::TopToolBarArea);
    //Qt::TopToolBarArea 两个工具栏上下排列
    ediToolBar = new QToolBar(tr("操作工具"));
    ediToolBar->addAction(operateAct);
    ediToolBar->addAction(newAct);
    ediToolBar->setMovable(false);
    addToolBar(ediToolBar);
}

QT入门之QMainWindow_第8张图片
这两个工具栏中间有一条横线间隔,且这两个工具栏是上下方向排列的
默认情况下是左右方向的:
QT入门之QMainWindow_第9张图片

5 setCentralWidget() 设置中心区域

顾名思义,中心区域就是窗口最中心的地方一般是用户主要操作的地方,比如,前面的 NodePad++ 的中心区域就是用户编辑文本的地方。

//将一个给定的 QWidget 作为中心区域
void QMainWindow::setCentralWidget(QWidget *widget)
//获取系统创建的中心区域
QWidget *QMainWindow::centralWidget() const

从这两个方法可以看出,只要是一个 widget 都可以作为中心区域。
简单示例:将一个 TextEdit 文本编辑框作为 centralWidget

void MainWindow::showCentralWidget(){
   centerTextEdit=new QTextEdit(this);
   centerTextEdit->setText(tr("这里是中心区域"));
   centerTextEdit->setAlignment(Qt::AlignCenter);
   setCentralWidget(centerTextEdit);
}

QT入门之QMainWindow_第10张图片
中间的文本编辑框就是我们的中心区域了,它在菜单栏、工具栏的下面,在状态栏的上面。

6 QDockWidget

QDockWidget类提供了一个特殊的窗口部件,它可以是被锁在 QMainWindow 窗口内部或者是作为顶级窗口悬浮在桌面上。
它可以围绕在中心区域的四周
,即四个方向都可以放置,与工具栏类似。

先看一个简单的示例:

void MainWindow::showDockWidget(){
    dock1 = new QDockWidget(tr("dock1"),this);
    dock1->setFeatures(QDockWidget::DockWidgetMovable);
    dock1->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
    QTextEdit *textEdit1=new QTextEdit();
    textEdit1->setText(tr("这是第一个 dockWidget,只能放在左部、右部,用户可以拖动位置"));
    dock1->setWidget(textEdit1);
    addDockWidget(Qt::RightDockWidgetArea,dock1);//默认在窗口的右部

    dock2 = new QDockWidget(tr("dock2"),this);
    dock2->setFeatures(QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetClosable);
    QTextEdit *textEdit2=new QTextEdit();
    textEdit2->setText(tr("这是第二个 dockWidget 只能放在下部、右部,用户可以将它拖出窗口,浮动在桌面上;也可以关闭它"));
    dock2->setWidget(textEdit2);
    addDockWidget(Qt::RightDockWidgetArea,dock2);
}

QT入门之QMainWindow_第11张图片

6.1 setFeatures()

上面的例子我们创建了两个 QDockWidget ,都通过 setFeatures() 设置了一些特性 :dock1 可以移动;dock2 可浮动和可关闭

可移动就是指用户可以将 dockWidget 从原本的右部拖到左部、下部等,至于可以拖动哪个部位则由 setAllowedAreas() 来控制

QT入门之QMainWindow_第12张图片
上图是将 dock1 移动到了窗口的左部。
QT入门之QMainWindow_第13张图片
上图是将 dock2 拖出了主窗口,让 dock2 悬浮在桌面上。因为我们给 dock2 设置了:

dock2->setFeatures(QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetClosable);

点击右上角的关闭按钮即可关闭 dock2 ,而 dock1 没有设置可关闭特性,则不能关闭。

到这里,QMainWindow 中的各个部件就简单的介绍完了,对于每个部件更加详细的介绍就在后面的文章介绍了。比如让部件的 UI 元素更加丰富,功能更强大。

7 保存 / 设置窗口状态

很多时候,用户在关闭软件后,会记录一下程序当前的状态,用户下次打开软件后,还是上一次退出时的状态。比如:wps 的最近打开的文件记录;对软件界面的大小设置、常用快捷键的设置等

下面两个方法可以保存窗口信息

QByteArray saveGeometry() const;//保存窗口大小
QByteArray saveState(int version = 0) const;//保存当前状态,QToolBar 和 QDockWidget,version 可以自己设置版本号

相反的方法就是设置状态了:

bool restoreGeometry(const QByteArray &geometry);
bool restoreState(const QByteArray &state, int version = 0);
7.1 简单示例:

我们拿前面的例子做一个简单示例,启动程序后,我们调整窗口的大小,并将 dock2 拖出窗口,然后关闭窗口,再次启动程序,将会是我们上一次关闭时的状态

//点击窗口的关闭按钮时执行
void MainWindow::closeEvent(QCloseEvent *event){
    QSettings settings("com.llk", "mainwindowtest");
    settings.beginGroup("mainWindow");
    settings.setValue("geometry", saveGeometry());
    settings.setValue("windowState", saveState());
    settings.endGroup();
    QMainWindow::closeEvent(event);
}
void MainWindow::readSettings(){
    QSettings settings("com.llk", "mainwindowtest");
    settings.beginGroup("mainWindow");
    //读取出保存的值,并设置到窗口中
    restoreGeometry(settings.value("geometry").toByteArray());
    restoreState(settings.value("windowState").toByteArray());
    settings.endGroup();
}

启动程序后,我们调整窗口的大小,再将 dock2 拖出窗口
QT入门之QMainWindow_第14张图片
然后关闭软件,再启动我们的程序,还将展示上图的界面,说明程序记录了我们前一次关闭时的状态。

【注意】readSettings(); 方法的调用应在各个部件创建完成后再调用,否则没有效果

这里我们是使用了 QSettings 类来帮我们存储窗口状态,其实我们也可以将数据保存到自己想保存的任意文件中,或是通过网络传给服务器保存都可以。只要将 saveGeometry() 和 saveState() 方法返回的字节数组的值保存起来,再次启动程序的时候再设置给 restoreGeometry() 和 restoreState() 即可。

8 完整代码

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include "qaction.h"
#include "qmenu.h"
#include "qmenubar.h"
#include "qstatusbar.h"
#include "qtoolbar.h"
#include "QDockWidget"
#include "qtextedit.h"
#include "QCloseEvent"
#include "qsettings.h"
#include "qdebug.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

private slots:
    void newActTriggered();
    void operateActTriggered();

public:
    QMenuBar *mBar;//菜单栏
    QMenu *fileMenu;
    QMenu *editMenu;
    QAction *newAct;
    QAction *operateAct;

    QStatusBar *sBar;//状态栏
    QToolBar *fileToolBar;//文件工具栏
    QToolBar *ediToolBar;//文件工具栏

    QTextEdit *centerTextEdit;

    QDockWidget *dock1;
    QDockWidget *dock2;


    MainWindow(QWidget *parent = 0);
    void showMenus();
    void showStatusBar();
    void showToolBar();
    void showCentralWidget();
    void showDockWidget();
    void closeEvent(QCloseEvent *event);
    void readSettings();
    ~MainWindow();
};

mainwindow.cpp:

#include "mainwindow.h"
//1、菜单栏
void MainWindow::showMenus()
{
    mBar = menuBar();
    fileMenu = mBar->addMenu(tr("文件"));
    editMenu = mBar->addMenu(tr("编辑"));
    operateAct = mBar->addAction(tr("操作"),this,SLOT(operateActTriggered()));

    newAct = new QAction("new");
    fileMenu->addAction(newAct);

    connect(this->newAct,SIGNAL(triggered()),this,SLOT(newActTriggered()));
}

//2、状态栏
void MainWindow::showStatusBar(){
    sBar = statusBar();

    sBar->showMessage(tr("这里是状态栏"),0);
}
//3、工具栏
void MainWindow::showToolBar(){
    fileToolBar = addToolBar(tr("文件工具"));
    fileToolBar->setObjectName("fileToolBar");
    fileToolBar->setMovable(false);
    fileToolBar->addAction(newAct);

    ediToolBar = new QToolBar(tr("操作工具"));
    ediToolBar->setObjectName("ediToolBar");
    ediToolBar->addAction(operateAct);
    ediToolBar->addAction(newAct);
    ediToolBar->setMovable(false);
    addToolBar(ediToolBar);
}

//4、中心区域
void MainWindow::showCentralWidget(){
    centerTextEdit=new QTextEdit(this);
    centerTextEdit->setText(tr("这里是中心区域"));
    centerTextEdit->setAlignment(Qt::AlignCenter);
    setCentralWidget(centerTextEdit);
}

//5、悬浮部件
void MainWindow::showDockWidget(){
    dock1 = new QDockWidget(tr("dock1"),this);
    dock1->setObjectName("dock1");
    dock1->setFeatures(QDockWidget::DockWidgetMovable);
    dock1->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea);
    QTextEdit *textEdit1=new QTextEdit();
    textEdit1->setText(tr("这是第一个 dockWidget,只能放在左部、右部,用户可以拖动位置"));
    dock1->setWidget(textEdit1);
    addDockWidget(Qt::RightDockWidgetArea,dock1);//默认在窗口的右部

    dock2 = new QDockWidget(tr("dock2"),this);
    dock2->setObjectName("dock2");
    dock2->setFeatures(QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetClosable);
    dock2->setAllowedAreas(Qt::BottomDockWidgetArea|Qt::RightDockWidgetArea);
    QTextEdit *textEdit2=new QTextEdit();
    textEdit2->setText(tr("这是第二个 dockWidget 只能放在下部、右部,用户可以将它拖出窗口,浮动在桌面上;也可以关闭它"));
    dock2->setWidget(textEdit2);
    addDockWidget(Qt::RightDockWidgetArea,dock2);
}

void MainWindow::closeEvent(QCloseEvent *event){
    QSettings settings("com.llk", "mainwindowtest");
    settings.beginGroup("mainWindow");
    settings.setValue("geometry", saveGeometry());
    settings.setValue("windowState", saveState());
    settings.endGroup();
    QMainWindow::closeEvent(event);
}

void MainWindow::readSettings(){
    QSettings settings("com.llk", "mainwindowtest");
    settings.beginGroup("mainWindow");
    restoreGeometry(settings.value("geometry").toByteArray());
    restoreState(settings.value("windowState").toByteArray());
    settings.endGroup();
}

void MainWindow::newActTriggered(){
    qDebug()<<"newActTriggered()";
}

void MainWindow::operateActTriggered(){
    qDebug()<<"operateTriggered()";
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    showMenus();
    showStatusBar();
    showToolBar();
    showCentralWidget();
    showDockWidget();
    readSettings();
}


MainWindow::~MainWindow()
{

}

main.cpp:

#include "mainwindow.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

你可能感兴趣的:(QT5.9,qt)