普通的桌面应用程序有个共同的特性,有菜单栏、工具栏、状态栏、中央窗口等部件。菜单栏其实可以看成是一个窗口,菜单栏中的每一个菜单也可以看成一个窗口,每个部件基本都可以认为是一个窗口。那么这些典型的桌面应用可以认为是一些QWidget的组合,通过QWidget派生的方式也确实能够完成这样的窗口。
但是如果每次都自己去设计,重复这些工作,想想都有些麻烦,于是Qt帮我们实现这样的窗口,叫做QMainWindow,QMainWindow已经布置好菜单栏、工具栏、状态栏等窗口,我们只需要懂得如何去应用就行了。
QMainWindow的布局
注:MenuBar是菜单栏,toolbars是工具栏,Dock Widgets是停口窗口,Central Widget是中央窗口,Status Bar是状态栏
QMainWindow工程的创建和前面《QT学习笔记 —— 2. 使用向导创建QT项目》流程一样,因此如果不会创建工程,可以参考前面创建工程的过程。整个过程只是下面这个步骤不一样。前面选择的基类是QWidget,现在需要选择QMainWindow作为基类。
一个主窗口最多只有一个菜单栏。在Qt中菜单栏类是QMenuBar,它也是继承至QWidget,菜单栏是一个长条状窗口,可以是横向也可以是纵向的,菜单栏上可以布置菜单。
通过QMainWindow::MenuBar() 来获取一个QMenuBar对象的指针, 如果该对象不存在, 就新建一个对象。这个函数只能创建一个菜单栏,函数原型如下:
QMenuBar *QMainWindow::menuBar() const
例如:
#include "mainwindow.h"
#include
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
QMenuBar* menuBar = this->menuBar();
}
也可以通过new一个QMenuBar对象,然后通过QMainWindow::setMenuBar来设置主窗口的菜单栏。
void QMainWindow::setMenuBar(QMenuBar *menuBar)
例如:
#include "mainwindow.h"
#include
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
QMenuBar* menuBar = new QMenuBar;
this->setMenuBar(menuBar);
}
创建完菜单栏之后,就可以在菜单栏上面布置菜单了,菜单类叫作QMenu,QMenu也是继承至QWidget。
QMenuBar对象中添加QMenu对象可以使用函数:
QAction *QMenuBar::addMenu(QMenu *menu) //添加一个已经创建好的QMenu对象
QMenu *QMenuBar::addMenu(const QString &title) //给定菜单标题,自动创建QMenu对象
QMenu *QMenuBar::addMenu(const QIcon &icon, const QString &title)//将带有图标和标题的新QMenu附加到菜单栏。菜单栏拥有菜单的所有权。返回新菜单。
例如:
#include "mainwindow.h"
#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QMenuBar* menuBar = this->menuBar();
QMenu *fileMenu = new QMenu("文件(&F)", menuBar);
menuBar->addMenu(fileMenu);
QMenu *editMenu = menuBar->addMenu("编辑(&E)");
}
菜单中的诸如打开、保存、关闭等,都是一个个动作,在Qt里面对应的类是QAction,它不是窗口类,它是继承至QObject。可以使用QMenu::addAction来添加动作,QMenu::addAction有多个重载的函数,都是返回一个新建的QAction对象。
QAction(QObject *parent = nullptr)
QAction(const QString &text, QObject *parent = nullptr)
QAction(const QIcon &icon, const QString &text, QObject *parent = nullptr)
添加一个最简单的动作
#include "mainwindow.h"
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->resize(600, 480);
QMenuBar * menuBar = this->menuBar();
QMenu * fileMenu = new QMenu("文件(&F)", menuBar);
menuBar->addMenu(fileMenu);
fileMenu->addAction("close");
}
Qt 并没有专门的菜单项类,只是使用一个QAction类,抽象出公共的动作。当我们把QAction对象添加到菜单,就显示成一个菜单项,添加到工具栏,就显示成一个工具按钮。用户可以通过点击菜单项、点击工具栏按钮、点击快捷键来激活这个动作。
分隔符可以起到修饰的作用,使用QMenu::addSeparator()添加分割符号。
QAction *QMenu::addSeparator()
工具栏类是QToolbar,QToolbar对象中可以布置一些QAction动作,QToolbar继承至QWidget,主窗口可以使用QMainWindow::addToolBar来添加工具栏。
QToolBar *QMainWindow::addToolBar(const QString &title) //创建一个窗口标题为title的工具栏
void QMainWindow::addToolBar(QToolBar *toolbar) //添加一个已经存在的toolbar对象
void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar)//添加一个已经存在的toolbar对象到指定区域,Qt::ToolBarArea是工具栏位置的枚举类型。
例如:
#include "mainwindow.h"
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->addToolBar("tool bar 1");
QToolBar* toolBar = new QToolBar("tool bar 2", this);
this->addToolBar(Qt::LeftToolBarArea, toolBar); //添加一个工具栏到左边区域。
}
工具栏上面也能添加动作QAction对象,使用QToolBar::addAction。
QAction对象可以复用,那么可以把菜单上面的动作对象拿下来使用。一般的桌面型应用菜单跟工具栏的动作往往是共用的。
QMainWindow中创建状态栏可以使用QMainWindow::statusBar
QStatusBar *QMainWindow::statusBar() const
如果QStatusBar对象不存在,就新建一个。如果存在就返回QStatusBar对象。用这个函数也只能创建一个QStatusBar对象。
也可以自己创建,然后使用QMainWindow::setStatusBar设置主窗口的状态栏
void QMainWindow::setStatusBar(QStatusBar *statusbar)
QMainWindow的中央窗口可以使用QMainWindow::CentralWidget来设置一个QWidget对象或者派生类对象作为主窗口的中央窗口。
void QMainWindow::setCentralWidget(QWidget *widget)
例如:
#include "mainwindow.h"
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QTextEdit * edit = new QTextEdit(this);
this->setCentralWidget(edit);
}
将一个QTextEdit作为主窗口的中央窗口,QTextEdit是一个文本编辑窗口,继承至QAbstractScrollArea。
Qt中停靠窗口类为QDockWidget,QDockWidget继承至QWidget,这种窗口可以停靠在主窗口的停靠区域。
QDockWidget构造函数有两个
QDockWidget::QDockWidget(const QString &title, QWidget *parent = nullptr, Qt::WindowFlags flags = ...)
QDockWidget::QDockWidget(QWidget *parent = nullptr, Qt::WindowFlags flags = ...)
QDockWidget对象并不能当作普通窗口来使用,但是可以在个窗口上嵌套一个普通窗口
void QDockWidget::setWidget(QWidget *widget) //用来设置一个普通窗口到停靠窗口中
首先创建好一个QMainWindow的工程,然后在mainwindow.cpp文件中添加一下代码,编译运行即可。当然项目文件中需要添加CONFIG += c++11,因为下面的代码用到了Lambda表达式。
#include "mainwindow.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//1. 菜单栏
QMenuBar *mBar = menuBar();
//添加菜单
QMenu *pFile = mBar->addMenu("文件");
//添加菜单项,添加动作
QAction *pNew = pFile->addAction("新建");
connect(pNew, &QAction::triggered,
[=]()
{
qDebug() << "新建被按下";
}
);
pFile->addSeparator();//添加分割线
QAction *pOpen = pFile->addAction("打开");
//2. 工具栏,菜单项的快捷键
QToolBar *toolBar = addToolBar("toolBar");
//工具栏添加快捷键
toolBar->addAction(pNew);
QPushButton *b = new QPushButton(this);
b->setText("^_^");
//添加小控件
toolBar->addWidget(b);
connect(b, &QPushButton::clicked,
[=]()
{
b->setText("123");
}
);
//3. 状态栏
QStatusBar *sBar = statusBar();
QLabel *label = new QLabel(this);
label->setText("Normal text file");
sBar->addWidget(label);
//addWidget 从左往右添加
sBar->addWidget(new QLabel("2",this));
//addPermanentWidget 从右往左添加
sBar->addPermanentWidget(new QLabel("3",this));
//4. 核心控件
QTextEdit *textEdit = new QTextEdit(this);
setCentralWidget(textEdit);
//5. 浮动窗口
QDockWidget *dock = new QDockWidget(this);
addDockWidget(Qt::RightDockWidgetArea, dock);
//给浮动窗口添加控件
QTextEdit *testEdit1 = new QTextEdit(this);
dock->setWidget(testEdit1);
}
MainWindow::~MainWindow()
{
}
编译运行即可。