目录
1.QMainWindow类介绍
我们之前学习的所有内容,都是基于QWidget这个类派生出来的各种控件。但是这些控件更多的时候是作为窗口的一部分。我们在创建项目的时候,选择的QMainWindow版本就是一个完整的窗口,是一个为用户提供窗口程序的类。当然也是继承与QWidget,但是是基于QWidget的基础上添加了菜单栏、多个工具栏、多个浮动窗口、状态栏以及一个中心部件。
QWidget版本的项目是不可以使用菜单栏等各种上述的内容的。
2.菜单栏-QMenuBar控件
Qt的菜单栏是通过QMenuBar这个类实现的,一个主窗口只能有一个菜单栏,但是菜单栏内部的菜单和选项是可以有多个的,每一个菜单是一个QMenu对象,每一个菜单选项是一个QAction对象。为什么不是QMenuItem呢?因为对于工具栏的功能来说和每一个菜单选项类似,所以说用一个统一的控件去实现两个栏的功能了。
创建菜单栏
有两种方法,第一种还是动态的在堆上创建一个QMenuBar对象,之后将菜单栏放入到窗口当中,第二种方法是使用QMainWindow类中提供的menuBar函数来创建菜单栏,之后同样也需要将菜单栏放入到窗口当中,这种方式不用手动的将菜单栏添加到对象树中。
QMenuBar* menuBar() const; //创建菜单栏函数
void setMenuBar(QMenuBar *menubar); //菜单栏设置到窗口
对于在创建菜单栏对象的时候会有两种情况,如果我们创建项目的时候没有勾选自动自动生成ui文件的话,是没有问题的。如果勾选了的话,qt会帮我们自动生成一个QMenuBar菜单栏对象,我们设置新的QMenuBar对象的话,就会导致旧的QMenuBar对象会脱离Qt的对象树,也就会导致我们无法对旧的QMenuBar就行释放操作,就会操作内存泄露了。
所以尽量还是使用第二种方式,执行的逻辑是如果有了就返回,没有的话再去创建之后再返回。
添加菜单和菜单选项
菜单是QMenu对象,菜单选项是QAction选项。
对于菜单也会有子菜单,子菜单中也可以有子菜单,那么对于QMenu类也是提供了addMenu的,可以在菜单中添加子菜单。当鼠标悬停到子菜单当中的时候,会展开子菜单。
QAction *addMenu(QMenu *menu); //添加菜单/子菜单
void addAction(QAction *action); //添加菜单选项
triggered信号
当我们创建完并设置好所有内容后,发现点击菜单项没有任何的反应,是因为系统也不知道我们要干什么,所以我们要自己去定义菜单选项对于的动作,用户点击菜单项之后,会触发一个QAction::trigged信号,我们定义这个信号的槽函数就好了。
设置快捷键
很简单,在设置菜单或者菜单选项文本的时候设置就可以了,在文本里面写上 &x 的格式就可以了。当然使用QShortCut来设置快捷键也是可以的。但是这么设置的话,就需要定义快捷键选项,然后设置快捷键对应的操作槽函数,很麻烦。这里括号带不带都可以。
这样设置的快捷键是要使用alt + x触发的。
QMenu* menu = new QMenu("文件 (&F)");
QAction* action = new QAction("新建文件 (&W)");
添加分割线
这个操作也很简单,就是调用QMenu类中提供的addSeperator函数即可。对于菜单选项展示的顺序是我们添加的顺序,我们可以把添加的分割线和他们看成一样的操作,也是根据顺序来进行的,所以如果我们想要在第二个和第三个菜单项之间添加分割线的话,就需要在第二个菜单项添加完毕之后添加分割线。
QAction *addSeparator();
添加图标
需要使用QIcon类,同时使用qrc机制这样会更好。 对于菜单、子菜单以及菜单选项都是可以设置图标的,但是对于菜单来说,设置图标的话,图标就把文本给覆盖了。因为主菜单的话是长在QMenuBar上的只提供了一个位置,而子菜单是长在菜单上的,会分别给图标和文本预留空间。
void setIcon(const QIcon &icon);
使用案例
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建菜单栏
QMenuBar* menubar = this->menuBar();
this->setMenuBar(menubar);
// QMenuBar* menubar1 = new QMenuBar(this);
// this->setMenuBar(menubar1);
//创建菜单
QMenu* menu1 = new QMenu("文件 (&F)");
QMenu* menu2 = new QMenu("编辑 (&E)");
QMenu* menu3 = new QMenu("菜单1 (&B)");
//创建子菜单
QMenu* menu4 = new QMenu("子菜单1");
QMenu* menu5 = new QMenu("子菜单2");
//添加到菜单栏中
menubar->addMenu(menu1);
menubar->addMenu(menu2);
menubar->addMenu(menu3);
//子菜单添加到菜单中
menu3->addMenu(menu4);
menu3->addMenu(menu5);
//创建菜单选项
QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("退出");
QAction* action3 = new QAction("Undo");
QAction* action4 = new QAction("Redo");
QAction* action5 = new QAction("菜单项1");
QAction* action6 = new QAction("菜单项2");
QAction* action7 = new QAction("菜单项3");
QAction* action8 = new QAction("菜单项4");
QAction* action9 = new QAction("菜单项5");
QAction* action10 = new QAction("菜单项6");
//将菜单选项添加到菜单中
menu1->addAction(action1);
menu1->addAction(action2);
menu2->addAction(action3);
menu2->addAction(action4);
menu3->addAction(action5);
menu3->addAction(action6);
//将菜单选项添加到子菜单中
menu4->addAction(action7);
menu4->addSeparator(); //添加分割线
menu4->addAction(action8);
menu5->addAction(action9);
menu5->addAction(action10);
//添加action对应的槽函数
connect(action1, &QAction::triggered, this, &MainWindow::handler);
connect(action2, &QAction::triggered, this, &MainWindow::close); //MainWindow自带的close关闭函数
//添加图标
menu1->setIcon(QIcon(":/people.png"));
menu4->setIcon(QIcon(":/people.png"));
action7->setIcon(QIcon(":/people.png"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handler()
{
qDebug() << "新建操作被触发了";
}
3.工具栏-QToolBar控件
工具栏是应用程序中继承各种功能实现的一个快捷的区域,是一个QToolBar控件对象,可以有多个工具栏也可以没有工具栏,并不是必须存在的。工具栏本身是一个可移动的控件,他的元素是由各种控件组成,通常是以图标形式展示的按钮。
使用介绍
创建直接在堆上创建即可,对于设置到窗口中这里并不是set开头的函数,而是add开头的,也暗示着菜单来只能设置一个,而工具栏可以一直添加。
void addToolBar(QToolBar *toolbar);
而对于工具栏的选项设置,也是QAction对象,所以跟添加菜单项的操作是一样的。对于工具栏和菜单栏通常是一起使用的,而且工具栏很多情况下是将菜单栏中的重要功能或者常用的功能在设置一遍,所以工具栏和菜单栏中的选项都是用QAction控件也可以让这种情况不用设置两个重复功能的不同控件了。
那么又会有问题了,一个QAction对象即是菜单栏的选项又是工具栏的选项,那么在对象树释放的时候,不会重复释放两吗,肯定不会的,可以使用引用计数,或者释放之前判断一下都可以解决该问题。
对于工具栏的QAction对象设置,它默认会帮我们也生成一个该QAction控件的toolTip属性。如果设置的是图标,那么也会覆盖文本,但是会以toolTip的方式展现出来。也可以自己手动刷设置。
void setToolTip(const QString &tip);
设置停靠位置
工具栏不同于窗口标题和菜单栏内容,他是可以设置在上下左右四个位置的,所以就对应有了工具栏的停靠位置这个属性。
Qt::LeftToolBarArea | 停靠在左侧 |
Qt::RightToolBarArea | 停靠在右侧 |
Qt::TopToolBarArea | 停靠在顶部 |
Qt::BottomToolBarArea | 停靠在底部 |
Qt::AllToolBarArea | 以上四个位置都可以停靠 |
如何设置呢?有两种方式,第一种是在将工具栏添加到窗口的时候通过参数设置,第二种方法是通过调用QToolBar类内部的接口设置。
void addToolBar(Qt::ToolBarArea area, QToolBar *toolbar);
void setAllowedAreas(Qt::ToolBarAreas areas);
但是二者也是有区别的,对于设置到窗口的时候设置的停靠位置是,该工具栏默认的停靠位置,而使用setAllowedAreas函数设置的停靠位置则是工具栏只能在的位置。通过allowedAreas函数也可以获取到工具栏允许停靠的区域。
设置浮动属性
浮动状态就是工具栏可以放在任意的位置,如果不能浮动的话,就只能放在边上。工具栏的浮动属性可以使用QToolBar类中的setFloatable函数进行设置的。
void setFloatable(bool floatable);
设置移动属性
如果设置为不可移动的话,就相当于把工具栏订死在设定的位置了,不可以移动更不可以浮动了。
void setMoveable(bool moveable);
使用案例
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建工具栏对象
QToolBar* toolbar1 = new QToolBar();
QToolBar* toolbar2 = new QToolBar();
//设置到窗口中
this->addToolBar(toolbar1); //停靠位置默认为左侧
this->addToolBar(Qt::LeftToolBarArea, toolbar2);
//创建工具栏选项
QAction* action1 = new QAction("动作1");
QAction* action2 = new QAction("动作2");
QAction* action3 = new QAction("动作3");
QAction* action4 = new QAction("动作4");
//添加到工具栏
toolbar1->addAction(action1);
toolbar1->addAction(action2);
toolbar2->addAction(action3);
toolbar2->addAction(action4);
//设置工具栏1可以停靠的位置
toolbar1->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
//设置浮动属性
toolbar1->setFloatable(true);
toolbar2->setFloatable(true);
//设置工具栏2不可以移动
toolbar2->setMovable(false);
}
4.状态栏-QStatusBar控件
对于状态栏是应用程序输出一些简要信息的区域,一般是位于主窗口的底部区域,一个窗口最多也只能有一个状态栏,在Qt中,状态栏是由QStatisBar控件类实现的。
状态栏的创建和设置
因为一个窗口只能由一个状态栏,而且Qt会帮我们自动的创建一个状态栏,所以说他的创建和菜单栏类似,可以调用窗口的statusBar函数来获取状态栏,如果有的话就返回状态栏对象,如果没有的话就创建之后在返回状态栏对象。
void setStatusBar(QStatusBar *statusbar);
状态栏添加信息
状态栏是用于输出一些简单信息的,这些信息可以分为三类,第一类是实时信息,可以显示一些程序执行的进度或执行的一些操作等提示信息,这类信息不会一直存在,而是会有一定的期限。第二类是永久信息,可以显示一些版本号、机构等内容,这类信息会永久存在。第三类就是进度信息,可以显示一些进度条提示等等内容,会随着任务的进度而动态变化。
对于实时信息和永久信息可以使用showMessage函数去设置,当timeout不传参数或者传递为0的时候,就表示永久消息,该时间的单位是ms级别的。
void showMessage(const QString &text, int timeout = 0);
状态栏嵌套控件
对于信息也就是文本,所以可以添加label控件来显示文本信息。添加控件的函数QStatusBar类中提供了两种,第一种是从左向右添加,第二种则相反。第一个参数是控件,第二个参数是拉伸系数。当然不仅仅是可以添加label控件,而是可以添加任何控件,例如进度条、按钮、时间等控件。
void addWidget(QWidget *widget, int stretch = 0);
void addPermanentWidget(QWidget *widget, int stretch = 0);
使用案例
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QStatusBar>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建状态栏
QStatusBar* statusbar = this->statusBar();
this->setStatusBar(statusbar);
//添加信息
// statusbar->showMessage("提示信息", 3000);
QLabel* label1 = new QLabel("左面的提示信息");
QLabel* label2 = new QLabel("右面的提示信息");
//添加控件
statusbar->addWidget(label1);
statusbar->addPermanentWidget(label2);
}
MainWindow::~MainWindow()
{
delete ui;
}
5.浮动窗口-QDockWidget控件
在Qt中浮动窗口也称为铆接部件,也可以说是作为子窗口的存在。
浮动窗口的使用
在Qt中浮动窗口是由QCockWidget控件实现的,可以在堆上动态创建多个浮动窗口,在创建的时候可以设置浮动窗口的文本。创建和设置到窗口的操作和工具栏是类似的。在设置浮动窗口到窗口的时候需要指明浮动窗口的位置,该位置参数和状态栏的类似。
explicit QDockWidget(const QString &title, QWidget *parent = nullptr,
Qt::WindowFlags flags = Qt::WindowFlags());
void addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget);
对于浮动窗口内部的内容,我们可以像浮动窗口里添加控件,可以直接添加,但是只能添加一个控件,如果我们想要添加多个控件的话,需要先创建一个QWidget窗口,之后所有的控件都设置到QWidget中,然后将QWidget添加到浮动窗口中。
void setWidget(QWidget *widget);
浮动窗口停靠位置
Qt::LeftDockWidgetArea | 停靠在左侧 |
Qt::RightDockWidgetArea | 停靠在右侧 |
Qt::TopDockWidgetArea | 停靠在顶部 |
Qt::BottomDockWidgetArea | 停靠在底部 |
Qt::AllDockWidgetArea | 以上四个位置都可以停靠 |
浮动窗口添加多个控件案例
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDockWidget>
#include <QPushButton>
#include <QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建浮动窗口
QDockWidget* dockwidget1 = new QDockWidget("浮动窗口1");
QDockWidget* dockwidget2 = new QDockWidget("浮动窗口2");
this->addDockWidget(Qt::LeftDockWidgetArea, dockwidget1);
this->addDockWidget(Qt::LeftDockWidgetArea, dockwidget2);
//添加控件到浮动窗口中
QPushButton* button1 = new QPushButton("按钮1");
dockwidget1->setWidget(button1);
//创建窗口
QWidget* container = new QWidget();
//创建布局管理器
QVBoxLayout* layout = new QVBoxLayout();
container->setLayout(layout);
//创建其他控件
QPushButton* button2 = new QPushButton("按钮2");
QPushButton* button3 = new QPushButton("按钮3");
QPushButton* button4 = new QPushButton("按钮4");
//将控件添加到布局管理器中
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
dockwidget2->setWidget(container);
}
MainWindow::~MainWindow()
{
delete ui;
}