目录
我们前面所学的代码都是基于QWidget,这是一个控件,它更多的是作为别的窗口的一个部分,当我们在创建Qt项目的时候就会选择使用QWidget,还可以使用QMainWindow,它就相当于一个窗口的完全体。
QmainWindow 是一个为用户提供主窗口程序的类,继承自 QWidget 类,并且提供了一个预定义的布局。QMainWindow 包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个子窗口(铆接部件)(dock widgets)、⼀个状态栏(status bar) 和⼀个中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。
Qt 中的菜单栏是通过 QMenuBar 这个类实现的,一个主窗口最多只有一个菜单栏,位于主窗口顶部,主窗口标题栏下面,拿Qt Creater举例,中间的就是菜单栏,里面是一个个菜单 ,点击一个菜单就会出现菜单项。
我们创建一个 QMainWindow 项目,转到图形化界面,这个窗口中默认就有这几个,有centralwidget、MenuBar和StatusBar。
第一栏就是菜单栏,直接往菜单栏中添加几个菜单,都是仿照 Qt 设置的,就会看到菜单栏中出现了变化,每个菜单都是QMenu,菜单项是QAction。
在操作的时候难免会出现一些小Bug,这也是避免不了的,可能是Qt Creater自身的问题,既然图形化界面有Bug,那么就使用代码创建菜单栏。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 1. 创建一个菜单栏 QMenuBar* menuBar = new QMenuBar(); this->setMenuBar(menuBar); // 设置到窗口 // 2. 创建菜单 QMenu* menu1 = new QMenu("文件"); QMenu* menu2 = new QMenu("编辑"); QMenu* menu3 = new QMenu("构建"); menuBar->addMenu(menu1); menuBar->addMenu(menu2); menuBar->addMenu(menu3); // 3. 创建菜单项 QAction* action1 = new QAction("新建"); QAction* action2 = new QAction("打开"); QAction* action3 = new QAction("保存"); QAction* action4 = new QAction("另存为"); QAction* action5 = new QAction("退出"); menu1->addAction(action1); menu1->addAction(action2); menu1->addAction(action3); menu1->addAction(action4); menu1->addAction(action5); }
既然创建出了菜单项,那就是要让菜单项提供某种功能,当用鼠标点击菜单项的时候,这次触发的就不是clicked信号了,而是triggered信号。
// 4. 连接信号和槽 connect(action5, &QAction::triggered, this, &QMainWindow::close); // 点击这个菜单项就退出Qt Creater中的菜单栏中还带有快捷键,使用Alt + 字母的方式就可以触发对应的菜单,打开对应的菜单项,我们上一篇中也提到了两种设置快捷键的方式,一种是通过QShortCut,但是这种设置比较麻烦,还有一种就是(&字母),通过这种方式就可以设置快捷键了。
// 2. 创建菜单 QMenu* menu1 = new QMenu("文件(&F)"); QMenu* menu2 = new QMenu("编辑(&E)"); QMenu* menu3 = new QMenu("构建(&B)"); menuBar->addMenu(menu1); menuBar->addMenu(menu2); menuBar->addMenu(menu3); // 3. 创建菜单项 QAction* action1 = new QAction("新建(&N)"); QAction* action2 = new QAction("打开(&O)"); QAction* action3 = new QAction("保存(&L)"); QAction* action4 = new QAction("另存为"); QAction* action5 = new QAction("退出(&X)");
这样就设置好了快捷键,并且&符号也没有显示出来。
既然可以添加菜单,那么菜单中不仅可以添加菜单项,也应该可以添加菜单。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QMenuBar* menuBar = new QMenuBar(); this->setMenuBar(menuBar); // 设置到窗口 QMenu* menuParent = new QMenu("父菜单"); QMenu* menuChild = new QMenu("子菜单"); menuBar->addMenu(menuParent); menuParent->addMenu(menuChild); QAction* action1 = new QAction("菜单项1"); QAction* action2 = new QAction("菜单项2"); QMenu* menuChild2 = new QMenu("子菜单2"); menuChild->addAction(action1); menuChild->addAction(action2); menuChild->addMenu(menuChild2); }
如果菜单中的菜单项特别多,那就可以通过分割线进行分组,比如创建和打开项目可以是一组,保存文件也可以是一组。QMenu 中提供了 addSeparator 这样的函数。
// 3. 创建菜单项 QAction* action1 = new QAction("新建(&N)"); QAction* action2 = new QAction("打开(&O)"); QAction* action3 = new QAction("保存(&L)"); QAction* action4 = new QAction("另存为"); QAction* action5 = new QAction("退出(&X)"); menu1->addAction(action1); menu1->addAction(action2); menu1->addSeparator(); menu1->addAction(action3); menu1->addAction(action4); menu1->addSeparator(); menu1->addAction(action5);
Qt 中也可以看到菜单不仅有菜单,还可以有它自己的图标。
保存图片还是使用qrc文件,创建这个菜单项后就可以通过QIcon设置菜单项的图标了。
还要注意的一点就是,这里设置的是菜单项,菜单也是可以设置图标的,但是菜单栏中的QMenu是在QMenuBar上的,所以图标就会覆盖文本,文本也就不显示了。
最后还有一点要注意,如果构造函数中什么都不写,项目自动生成的ui文件中会自动带有QMenuBar,如果在构造函数中new一个 QMenuBar ,这就会导致旧的脱离 Qt 的对象树,后续也就无法自动释放了,这就造成了内存泄漏。
如果程序关闭,对象树释放了,进程结束后所有的内存都会被系统回收,这种内存泄漏也不会造成影响。
如果在一个多窗口程序中,窗口频繁的跳转和切换,也就对应了窗口的创建和销毁,这种内存泄漏还要严重一点。
实际上,现在的计算机内存都比较充裕,这种内存泄漏不会有太大的影响,这是因为是客户端程序,如果一个服务器出现内存泄漏,那就是致命的,服务器要一直运行,处理请求的过程中,每次都泄漏一点,时间久了就会泄漏很多。
所以我们也尽量不要出现这种内存泄漏,如何解决,那就不创建新的QMenuBar就好了。
这个操作就是如果QMenuBar存在,直接获取并返回;如果不存在,就创建一个再返回。
工具栏是应用程序中集成各种功能实现快捷键使用的一个区域,可以有多个,也可以没有,它并不是应用程序中必须存在的组件,往往是把我们常用的一些工具放到这里面。它是⼀个可移动的组件,它的元素可以是各种窗口组件,它的元素通常以图标按钮的方式存在。
现在就简单实现一个工具栏。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 手动创建工具栏 QToolBar* toolBar = new QToolBar(); this->addToolBar(toolBar); // 这里使用的add(添加),而菜单栏使用的是set(替换),由此也可以看出工具栏可以有多个,而菜单栏只能有一个 QAction* action1 = new QAction("新建文件或项目"); QAction* action2 = new QAction("打开文件或项目"); // 添加到工具栏,并加上图标 toolBar->addAction(action1); action1->setIcon(QIcon(":/image/file.png")); toolBar->addAction(action2); action2->setIcon(QIcon(":/image/directory.png")); }
从这个ToolTip就可以看到,工具栏也是把文本覆盖,如果想要改变,那就重新设置一下ToolTip,我们平常看到的工具栏也是一个一个的图标。
一个菜单项不仅可以添加到工具栏,也可以添加到菜单中,我们可以获取菜单栏,创建一个菜单,将菜单项分别添加到菜单和工具中,工具栏也是从菜单栏中取出常用的工具而已。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 获取菜单栏 QMenuBar* menuBar = this->menuBar(); this->setMenuBar(menuBar); // 创建菜单 QMenu* menu = new QMenu("文件"); menuBar->addMenu(menu); // 手动创建工具栏 QToolBar* toolBar = new QToolBar(); this->addToolBar(toolBar); // 这里使用的add(添加),而菜单栏使用的是set(替换),由此也可以看出工具栏可以有多个,而菜单栏只能有一个 // 创建两个菜单项 QAction* action1 = new QAction("新建文件或项目"); QAction* action2 = new QAction("打开文件或项目"); // 添加到工具栏,并加上图标 toolBar->addAction(action1); action1->setIcon(QIcon(":/image/file.png")); toolBar->addAction(action2); action2->setIcon(QIcon(":/image/directory.png")); // 也可以添加到菜单栏 menu->addAction(action1); menu->addAction(action2); }
由上图可知,这个工具栏不仅可以在菜单栏的下方,还可以在右侧,可以浮动在界面上,也可以有多个工具栏,所以可以对工具栏进行一些设置:
- 出现的初始位置
- 允许停放到哪些边缘
- 是否允许浮动
- 是否可以移动
在 QMainWindow 的 addToolBar中可以指定工具栏初始出现的位置,具体的选项也包括这几个。
Qt::LeftToolBarArea // 停靠在左侧 Qt::RightToolBarArea // 停靠在右侧 Qt::TopToolBarArea // 停靠在顶部 Qt::BottomToolBarArea // 停靠在底部 Qt::AllToolBarAreas // 以上四个位置都可停靠还可以设置允许停放到哪些边缘,通过 QToolBar 中的 setAllowedAreas 方法就可以设置。我们可以设置工具栏1只能停在上下,工具栏2只能停在左右。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 获取菜单栏 QMenuBar* menuBar = this->menuBar(); this->setMenuBar(menuBar); // 创建两个工具栏 QToolBar* toolBar1 = new QToolBar(); this->addToolBar(toolBar1); QToolBar* toolBar2 = new QToolBar(); this->addToolBar(Qt::LeftToolBarArea, toolBar2); toolBar1->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); toolBar2->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea); // 创建两个菜单项 QAction* action1 = new QAction("新建文件或项目"); QAction* action2 = new QAction("打开文件或项目"); // 添加到工具栏,并加上图标 toolBar1->addAction(action1); action1->setIcon(QIcon(":/image/file.png")); toolBar2->addAction(action2); action2->setIcon(QIcon(":/image/directory.png")); }
工具栏默认是可以浮动的,也就是拖动工具栏可以让他停在界面中,如果设置了不可浮动,那么工具栏就会自动停靠,设置方法就要通过QToolBar中的setFloatable方法。
// ... // 创建两个工具栏 QToolBar* toolBar1 = new QToolBar(); this->addToolBar(toolBar1); QToolBar* toolBar2 = new QToolBar(); this->addToolBar(Qt::LeftToolBarArea, toolBar2); // 设置允许停靠位置 toolBar1->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); toolBar2->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea); // 设置浮动属性 toolBar1->setFloatable(false); toolBar2->setFloatable(false); //...
如果工具栏设置成了不可移动,那么工具栏就只能停留在初始位置了,想要设置移动属性就要通过QToolBar中的setMovable。
// 创建两个工具栏 QToolBar* toolBar1 = new QToolBar(); this->addToolBar(toolBar1); QToolBar* toolBar2 = new QToolBar(); this->addToolBar(Qt::LeftToolBarArea, toolBar2); // 设置允许停靠位置 toolBar1->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); toolBar2->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea); // 设置浮动属性 toolBar1->setFloatable(false); toolBar2->setFloatable(false); // 设置不可移动 toolBar1->setMovable(false); toolBar2->setMovable(false);
效果就是工具栏只能停在初始位置,而且可拖动的图标也不见了。
状态栏往往是界面最下面一行,是应用程序中输出简要信息的区域,在Qt中是通过QStatusBar实现的,在状态栏中可以显示的消息类型有:
- 实时消息:如当前程序状态。
- 永久消息:如程序版本号。
- 进度消息:如进度条,百分号形式提示。
上面我们也展示过ui文件中会创建MenuBar,也会创建StatusBar,所以它也要注意内存泄漏的问题。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 获取状态栏 QStatusBar* statusBar = this->statusBar(); this->setStatusBar(statusBar); }
通过 showMessage 方法来实现。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 获取状态栏 QStatusBar* statusBar = this->statusBar(); this->setStatusBar(statusBar); // 显示实时消息 statusBar->showMessage("这是一个消息,3000毫秒后消失", 3000); }这个方法第一个参数就是文本,类型为QString;第二个参数为时间,类型为int,单位为ms,如果不填默认为0,消息永久存在。
在状态栏中也是可以添加控件的,添加控件的方式有两种,分别是addWidget和addPermanentWidget,第一种是从左往右添加控件,第二种是从右往左添加控件,而且控件之间也可以设置拉伸系数。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 获取状态栏 QStatusBar* statusBar = this->statusBar(); this->setStatusBar(statusBar); QLabel* label = new QLabel("这是一个QLabel"); statusBar->addWidget(label, 1); QLineEdit* lineEdit = new QLineEdit(); lineEdit->setPlaceholderText("这是一个QLineEdit"); statusBar->addPermanentWidget(lineEdit, 1); }
在 Qt 中,浮动窗口也被称为子窗口,浮动窗口是通过 QDockWidget 来实现浮动的功能。浮动窗口一般是位于核心部件的周围,可以有多个。
创建浮动窗口就要使用QDockWidget,这个函数也有两个参数,一个是位置参数,一个是要添加的浮动窗口。
位置参数和上面的工具栏的参数差不多,名字是不同的。
Qt::LeftDockWidgetArea 停靠在左侧 Qt::RightDockWidgetArea 停靠在右侧 Qt::TopDockWidgetArea 停靠在顶部 Qt::BottomDockWidgetArea 停靠在底部 Qt::AllDockWidgetAreas 以上四个位置都可停靠这就可以把我们之前学习过的控件结合起来。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 给主窗口添加一个子窗口 QDockWidget* dockWidget = new QDockWidget(); // 使用addDockWidget方法把浮动窗口添加到主窗口中 this->addDockWidget(Qt::TopDockWidgetArea, dockWidget); // 设置浮动窗口的标题 dockWidget->setWindowTitle("这是一个浮动窗口"); // 给浮动窗口内部添加一些其他控件 // 但是一个dockWidget只能添加一个控件,所以要添加一个QWidget,再往QWidget中添加控件 // 最后再把QWidget设置到dockWidget中 QWidget* widget = new QWidget(); dockWidget->setWidget(widget); // 创建水平布局管理器,把管理器添加到QWidget中 QVBoxLayout* layout = new QVBoxLayout(); widget->setLayout(layout); // 创建一个其他控件到layout中 QLabel* label = new QLabel("这是一个QLabel"); QPushButton* button = new QPushButton("这是一个按钮"); layout->addWidget(label); layout->addWidget(button); }
对话框时图形化开发程序中不可或缺的组成部分。它就是平常使用电脑时弹出的一个框,主要就是为了实现一些“短平快”的操作,它通常是一个顶层窗口 ,出现在程序的最上层,Qt中常用的内置对话框有:QFileDialog(文件对话框)、QColordialog(颜色对话框)、QFontDialog(字体对话框)、QInputDialog(输入对话框)和QMessageBox(消息框)。
在创建项目的时候也是除了可以选择创建QWidget和QMainWindow,还可以选择创建QDialog,这几种项目的创建就是改了一下继承的类名,差别也不大。除了QMainWindow,它和QWidget也是差不多的。
它也继承了QWidget,并且也有自己的属性。
当然实际开发中往往不会在创建项目时就创建一个继承了的QDiglog,而是在代码中创建额外的类,让这个类继承QDialog。
我们还是使用QMainWindow来实现对话框,通过点击一个按钮,弹出一个对话框。
void MainWindow::on_pushButton_clicked() { QDialog* dialog = new QDialog(this); // 设置标题 dialog->setWindowTitle("对话框标题"); // 调整大小 dialog->resize(300, 200); // show方法,显示对话框 dialog->show(); }
我们可以不断点击按钮来创建对话框,不同于其他控件的是,每次都会创建一个新的对话框,但是不释放就会造成内存泄漏。
既然出现内存泄漏,那简单,释放一下不就好了吗,在槽函数最后delete一下这个QDialog,那就会出现新的问题,这个对话框也就存在了一瞬间,每次点击按钮clicked函数中创建和销毁都会执行,所以也不能在这里delete。
正确的方式是在点击对话框的关闭按钮再释放。
void MainWindow::on_pushButton_clicked() { QDialog* dialog = new QDialog(this); // 设置标题 dialog->setWindowTitle("对话框标题"); // 调整大小 dialog->resize(300, 200); // show方法,显示对话框 dialog->show(); // 把delete和关闭按钮的点击信号关联起来 // Qt中给QDialog设置一个属性就可以在关闭的时候触发delete,参数是Qt内置的功能 dialog->setAttribute(Qt::WA_DeleteOnClose); }
前面也说过,想要自定义对话框通常要继承QDialog创建一个类,我们先来通过代码的方式创建一个对话框。
我们先新建一个类,类名和它的父类写上,点击下一步就可以了。
在构造函数中添加一个参数,这样就可以让我们的类也指定一个父元素,从而挂到对象树上。
在mainwindow.cpp中包含dialog.h(头文件),槽函数没有太大变化。
现在对话框就可以显示出来了,再向里面加入一些控件,现在Dialog就是父窗口了,所以就要在dialog.cpp中也就是dialog的构造函数中添加控件。
以上就是代码的创建方式,下面我们就来看看如何使用图形化界面的方式设置对话框,在创建项目的时候选择下面的文件和类中的Qt,选择Qt 设计师界面类。
界面模版还是选择Dialog,并且没有button的这一个。
创建好后就可以看到项目中出现了两个ui文件。
之后我们就可以通过拖拽把控件添加到界面。
然后写好两个槽函数就可以了。
上面我们说对话框也有自己的属性,其中有一个是modal,把对话框分为模态对话框和非模态对话框。
模态对话框弹出的时候,用户无法操作父窗口,必须要执行完对话框的操作,关闭对话框之后才可以操作父窗口;非模态对话框弹出的时候,用户是可以操作父窗口的。
可以试一下,如果不勾选这个属性,那么弹出对话框就可以一直操作,弹出无数个对话框。
所以模态就用于关键场合,用户必须做出决策。
前面我们使用的是show这个方法,还有一个方法是exec,这就可以生成一个模态对话框。
对话框一开始我就说过了Qt中有多种内置的可复用的对话框,他们都继承了QDialog,下面我们就逐个看看他们是怎样的。
消息对话框是应用程序中最常用的界面元素。消息对话框主要用于为用户提示重要信息,强制用户进行选择操作。
void MainWindow::on_pushButton_clicked() { // 创建 QMessageBox QMessageBox* messageBox = new QMessageBox(this); messageBox->setAttribute(Qt::WA_DeleteOnClose); // 关闭后释放 messageBox->setWindowTitle("MessageBox标题"); messageBox->setText("MessageBox本文"); messageBox->setIcon(QMessageBox::Warning); // 图标 messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel); // 按钮 // QMessageBox通常是模态的 messageBox->exec(); }这些图标和按钮也是Qt内置的,是自动生成的。
enum Icon { // keep this in sync with QMessageDialogOptions::Icon NoIcon = 0, // 无图标 Information = 1, // 提示 Warning = 2, // 警告 Critical = 3, // 严重 Question = 4 // 疑问 }; enum StandardButton { // keep this in sync with QDialogButtonBox::StandardButton and QPlatformDialogHelper::StandardButton NoButton = 0x00000000, Ok = 0x00000400, Save = 0x00000800, SaveAll = 0x00001000, Open = 0x00002000, Yes = 0x00004000, YesToAll = 0x00008000, No = 0x00010000, NoToAll = 0x00020000, Abort = 0x00040000, Retry = 0x00080000, Ignore = 0x00100000, Close = 0x00200000, Cancel = 0x00400000, Discard = 0x00800000, Help = 0x01000000, Apply = 0x02000000, Reset = 0x04000000, RestoreDefaults = 0x08000000, FirstButton = Ok, // internal LastButton = RestoreDefaults, // internal YesAll = YesToAll, // obsolete NoAll = NoToAll, // obsolete Default = 0x00000100, // obsolete Escape = 0x00000200, // obsolete FlagMask = 0x00000300, // obsolete ButtonMask = ~FlagMask // obsolete };
除了QMessageBox中的setStandardButtons方法,使用Qt自动生成的按钮,还可以添加按钮,使用的是addButton方法,这个方法的第一个参数为要添加的按钮,第二个参数为ButtonRole类型,这也是QMessageBox中的一个枚举类型。
void MainWindow::on_pushButton_clicked() { // 创建 QMessageBox QMessageBox* messageBox = new QMessageBox(this); messageBox->setAttribute(Qt::WA_DeleteOnClose); // 关闭后释放 messageBox->setWindowTitle("MessageBox标题"); messageBox->setText("MessageBox本文"); messageBox->setIcon(QMessageBox::Warning); // 图标 QPushButton* button = new QPushButton("按钮", messageBox); messageBox->addButton(button, QMessageBox::AcceptRole); // 表示Ok,接受 // QMessageBox通常是模态的 messageBox->exec(); }
如果不添加我们自己创建的按钮,那该如何使用信号和槽呢?Qt中setStandardButtons是自动生成的按钮,也无法关联槽函数。
关联信号和槽也比较“麻烦”,不使用信号和槽也可以获取按钮信息,对话框设置好后,需要使用exec方法弹出模态对话框,这个方法就可以获取点击按钮的返回值,通过这个返回值就可以知道用户点击了那个按钮。
void MainWindow::on_pushButton_clicked() { // 创建 QMessageBox QMessageBox* messageBox = new QMessageBox(this); messageBox->setAttribute(Qt::WA_DeleteOnClose); // 关闭后释放 messageBox->setWindowTitle("MessageBox标题"); messageBox->setText("MessageBox本文"); messageBox->setIcon(QMessageBox::Warning); // 图标 messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel); // 按钮 // QMessageBox通常是模态的 int result = messageBox->exec(); if (result == QMessageBox::Ok) { qDebug() << "Ok"; } else if (result == QMessageBox::Save) { qDebug() << "Save"; } else if (result == QMessageBox::Cancel) { qDebug() << "Cancel"; } }
创建对话框的方法不止这一种,还有一种就是使用QMessageBox中的静态函数。
void MainWindow::on_pushButton_clicked() { QMessageBox::warning(this, "MessageBox标题", "MessageBox文本", QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel); }就这短短的一行就可以支持我们刚才的功能,这个函数也是支持返回值的,所以想要获取返回值就可以拿一个int类型的变量获取。
所以,如果想要在对话框中实现一些简单的功能,就可以使用这种方式,如果想要在对话框中添加一些控件,还是使用上面的方式更好。
颜色对话框是允许用户选择颜色的,它也继承了QDialog,具体的就是显示一个调色板。
下面我们就看看Qt中如何弹出一个QColorDialog。
void MainWindow::on_pushButton_clicked() { QColorDialog* colorDialog = new QColorDialog(this); colorDialog->exec(); colorDialog->setAttribute(Qt::WA_DeleteOnClose); }
但是通常不会使用这种方法,我们使用的是QColorDialog中的getColor方法,这个方法能够弹出一个模态对话框,用户选择颜色,确认后关闭,getColor返回一个值,这就是用户选择的值,是不是很像QMessageBox中的静态函数,它其实也是一个静态函数,不用创建对话框对象就可以直接使用。
void MainWindow::on_pushButton_clicked() { QColor color = QColorDialog::getColor(QColor(0, 0, 0), this, "QColorDialog"); qDebug() << color; }这个函数的第一个参数类型为QColor,为初始默认值;第二个参数为parent,为父元素;第三个参数为标题;第四个参数是一个选项。
通过打印返回值我们可以看到,返回值的形式是ARGN的形式,A为alpha,不透明度,所以第一个参数就是它,后面也是使用0~1的小数表示RGB的值。
void MainWindow::on_pushButton_clicked() { QColor color = QColorDialog::getColor(QColor(0, 0, 0), this, "QColorDialog"); qDebug() << color; // 基于这个颜色修改窗口的背景色 // 可以通过QSS的方式设置背景色 QString style = "background-color: rgb(" + QString::number(color.red()) + ", " \ + QString::number(color.green()) + ", "\ + QString::number(color.blue()) + ");"; this->setStyleSheet(style); }
文件对话框用于应用程序中需要打开一个外部文件或需要当前内容存储到指定的外部文件。
它的常用方法有:
- 打开文件 (一次只能打开一个文件)
QString getOpenFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options());- 打开多个文件 (一次可以打开多个文件)
QStringList getOpenFileNames(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options());- 保存文件
QString getSaveFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options());下面看看弹出的对话框是什么样的。
void MainWindow::on_pushButton_clicked() { QString filePath = QFileDialog::getOpenFileName(this); qDebug() << filePath; } void MainWindow::on_pushButton_2_clicked() { QString filePath = QFileDialog::getSaveFileName(this); qDebug() << filePath; }在打开文件的对话框中,点击按钮,点击打开就会返回这个文件的路径,上面还有一个类似ComboBox的下拉框,这就是文件的类型,可以在getOpenFileName的filter参数中设置。
保存文件的对话框据需要输入要保存文件的文件名,输入后点击保存就会返回这文件的路径。
虽然可以返回路径,由于没有后续操作,所以只是返回路径而已,上述两种功能都是需要额外去实现的。
Qt 中提供了预定义的字体对话框类,这个对话框可以支持选择字体,使用方法也是类似的,getFont,返回一个QFont对象。
void MainWindow::on_pushButton_clicked() { bool ok = false; QFont font = QFontDialog::getFont(&ok, this); qDebug() << ok; qDebug() << font; }这个方法的参数第一个是一个bool值,作为输出型参数,如果点击了OK,返回true,如果直接关闭的对话框或点击Cancel,那就是false。
我们就可以通过获取的QFont对象给其他控件设置Font属性。
void MainWindow::on_pushButton_clicked() { bool ok = false; QFont font = QFontDialog::getFont(&ok, this); qDebug() << ok; qDebug() << font; if (ok == true) ui->pushButton->setFont(font); }
Qt 中提供了预定义的输入对话框类,用于临时数据的输入。
它有这几个静态方法,getInt(输入整数)、getDouble(输入双精度浮点数)、getItem他们几个的静态方法都差不多,参数也差不多,一看也就明白了。
void MainWindow::on_pushButton_clicked() { int result = QInputDialog::getInt(this, "整数输入", "请输入一个整数"); qDebug() << result; } void MainWindow::on_pushButton_2_clicked() { double result = QInputDialog::getDouble(this, "浮点数输入", "请输入一个浮点数"); qDebug() << result; } void MainWindow::on_pushButton_3_clicked() { QStringList items; items.push_back("第1个"); items.push_back("第2个"); items.push_back("第3个"); QString item = QInputDialog::getItem(this, "条目型输入", "请输入", items); qDebug() << item; }
对于 Qt 中窗口的设置已经了解的差不多了。现在我们知道,一个窗口包括:
- 菜单栏(QMenuBar)
- 菜单(QMenu)
- 菜单项(QAction)
- 工具栏(QToolBar)
- 菜单项(QAction)
- 子窗口(QDockWidget)
- QWidget
- 其他控件
- 状态栏(QStatusBar)
- QWidget
- 对话框(QDialog)
- 内置的对话框
一个窗口可以包含这么多的元素,上一篇中的Widget可能只是一个窗口,但实际的程序就有多个窗口多个对话框等一同构成的。