目录
6. 对话框(QFiledialog,QColorDialog,QFontDialog,QInputDialog,QMessageBox)
1. 前言
Qt窗口时通过QMainWindow类来实现的。
QMainWindow是一个为用户提供主窗口程序的类,继承自QWidget类,并且提供了一个预定义的布局。QMainWindow包含一个菜单栏(menu bar),多个工具栏(tool bars), 多个浮动窗口(dock widgets),一个状态栏(status bar)和一个中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。如下图为QMainWindow中各组件所处的位置
2. 菜单栏(QMenuBar)
Qt中的菜单栏是通过QMenuBar这个类来实现的。一个主窗口最多只有一个菜单栏。位于主窗口顶部,主窗口标题栏下面。
菜单栏包含菜单,菜单中包含菜单项
2.1. 创建菜单栏
2.1.1. 方式一
菜单栏的创建可以借助于QMainWindow类提供的menuBar()函数来实现。menubar()函数原型如下:
2.1.2. 方式二
在堆上动态创建
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menu = new QMenuBar(this);
menu->addAction("菜单");
menu->addAction("编辑");
menu->addAction("视图");
menu->addAction("关于");
this->setMenuBar(menu);
}
使用setMenuBar把菜单放到窗口中.
2.2. 在菜单栏中添加菜单和创建菜单项
创建菜单,并通过QMenu提供的addMenu()函数来添加菜单
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menu = new QMenuBar(this);
// 创建菜单
QMenu* m1 = new QMenu("文件");
QMenu* m2 = new QMenu("编辑");
// 将菜单添加到菜单栏上
menu->addMenu(m1);
menu->addMenu(m2);
// 创建菜单项
QAction* action = new QAction("打开文件夹");
QAction* action1 = new QAction("save");
// 将菜单项添加到菜单上
m1->addAction(action);
m2->addAction(action1);
this->setMenuBar(menu);
}
2.3. 在菜单项之间添加分割线
在菜单项之间可以添加分割线。分割线是通过QMenu类提供的addSeparator()函数来实现的。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar* menu = new QMenuBar(this);
QMenu* m1 = new QMenu("文件");
QMenu* m2 = new QMenu("编辑");
menu->addMenu(m1);
menu->addMenu(m2);
QAction* action = new QAction("打开文件夹");
QAction* action1 = new QAction("save");
m1->addAction(action);
m1->addSeparator(); // 在action和action1中间添加分割线
m1->addAction(action1);
this->setMenuBar(menu);
}
2.4. 综合示例
- 新建Qt项目(基类选择QMainWindow)
- 在mainwindow.cpp文件中创建菜单和中央空间
创建一个菜单栏,一个菜单。两个菜单项:保存和加载。创建一个QTextEdit作为窗口的中央空间
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 设置标题
this->setWindowTitle("我的记事本");
// 创建菜单栏
QMenuBar* menuBar = new QMenuBar(this);
this->setMenuBar(menuBar);
// 创建菜单
QMenu* menu = new QMenu("文件");
menuBar->addMenu(menu);
// 创建菜单项
QAction* action1 = new QAction("保存");
QAction* action2 = new QAction("加载");
menu->addAction(action1);
menu->addAction(action2);
// 创建中央控件
QTextEdit* edit = new QTextEdit(this);
this->setCentralWidget(edit);
edit->setPlaceholderText("此处编写文本内容...");
}
- 给action添加一些动作
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QTextEdit>
#include <QFileDialog>
#include <QDebug>
#include <fstream>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 设置标题
this->setWindowTitle("我的记事本");
// 创建菜单栏
QMenuBar* menuBar = new QMenuBar(this);
this->setMenuBar(menuBar);
// 创建菜单
QMenu* menu = new QMenu("文件");
menuBar->addMenu(menu);
// 创建菜单项
QAction* action1 = new QAction("保存");
QAction* action2 = new QAction("加载");
menu->addAction(action1);
menu->addAction(action2);
// 创建中央控件
edit = new QTextEdit(this);
this->setCentralWidget(edit);
edit->setPlaceholderText("此处编写文本内容...");
connect(action1, &QAction::triggered, this, &MainWindow::save);
connect(action2, &QAction::triggered, this, &MainWindow::load);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::save() {
QFileDialog* dialog = new QFileDialog(this);
QString fileName = dialog->getSaveFileName(this, "保存文件","C:/User/1/");
qDebug() << "file name" << fileName;
std::ofstream file(fileName.toStdString().c_str());
if (!file.is_open()) {
qDebug() << "save file";
return;
}
const QString& text = edit->toPlainText();
file << text.toStdString();
file.close();
}
void MainWindow::load() {
QFileDialog* dialog = new QFileDialog(this);
QString fileName = dialog->getOpenFileName(this, "load file", "C:/Users/1/");
qDebug() << "fileName: " << fileName;
// 读取⽂件
std::ifstream file(fileName.toStdString().c_str());
if (!file.is_open()) {
qDebug() << "⽂件加载失败!";
return;
}
std::string content;
std::string line;
while (std::getline(file, line)) {
content += line;
content += "\n";
}
file.close();
// 显⽰到界⾯上
QString text = QString::fromStdString(content);
edit->setPlainText(text);
}
执行程序就可以保存文件和加载文件了。
3. 工具栏(QToolBar)
工具栏是应用程序中集成各种功能实现快捷键使用的一个区域。可以有多个,也可以没有,它并不是应用程序中必须存在的组件。它是一个可移动的组件。它的元素可以是各种窗口组件,它的元素通常以图标按钮的方式存在。
3.1. 创建工具栏
调用QMainWindow类的addToolBoar()函数来创建工具栏,每增加一个工具栏都需要调用一次该函数。
QToolBar* toolBar1 = new QToolBar(this);
QToolBar* toolBar2 = new QToolBar(this);
this->addToolBar(toolBar1);
this->addToolBar(toolBar2);
3.2. 设置停靠位置
工具栏停靠位置的设置有两种方式。一种是在创建工具栏的同时指定停靠的位置,另一种是通过QToolBar提供的setAllowedAreas()函数来设置。
3.2.1. 方式一
创建工具栏的同时指定停靠的位置。
在创建工具栏的同时,也可以设置工具栏的位置,其默认位置是在窗口的最上面;如上述代码,默认在最上面显示。工具栏允许停靠的区域由QToolBar类提供的allowAreas()函数决定,其中可以设置的位置包括
Qt::LeftToolBarArea |
停靠在左侧 |
Qt::RightToolBarArea |
停靠在右侧 |
Qt::TopToolBarArea |
停靠在顶部 |
Qt::BottomToolBarArea |
停靠在底部 |
Qt::AllToolToolBarArea |
以上四个位置都可以停靠 |
QToolBar* toolBar1 = new QToolBar(this);
QToolBar* toolBar2 = new QToolBar(this);
this->addToolBar(Qt::LeftToolBarArea,toolBar1);
this->addToolBar(Qt::RightToolBarArea,toolBar2);
3.2.2. 方式二
使用QToolBar类提供的setAllowedAreas()函数设置停靠位置
this->addToolBar(toolBar1);
this->addToolBar(toolBar2);
toolBar1->setAllowedAreas(Qt::LeftToolBarArea);
toolBar2->setAllowedAreas(Qt::RightToolBarArea);
说明:
在创建⼯具栏的同时指定其停靠的位置,指的是程序运⾏时⼯具栏默认所在的位置;⽽使⽤
setAllowedAreas()函数设置停靠位置,指的是⼯具栏允许其所能停靠的位置。
3.3. 设置浮动属性
⼯具栏的浮动属性可以通过 QToolBar类 提供的setFloatable()函数来设置。setFloatable()函数原型为:
void setFloatable(boolfloatable)
参数:true:浮动
false:不浮动
this->addToolBar(Qt::LeftToolBarArea, toolBar1);
this->addToolBar(Qt::RightToolBarArea,toolBar2);
toolBar1->setFloatable(true);
toolBar2->setFloatable(false);
3.4. 设置移动属性
设置⼯具栏的移动属性可以通过QToolBar类提供的setMovable()函数来设置。setMovable()函数
原型为:
void setMovable(boolmovable)
参数:true:移动
false:不移动
说明:若设置⼯具栏为不移动状态,则设置其停靠位置的操作就不会⽣效,所以设置⼯具栏
的移动属性类似于总开关的效果
QToolBar* toolBar1 = new QToolBar(this);
QToolBar* toolBar2 = new QToolBar(this);
this->addToolBar(Qt::LeftToolBarArea, toolBar1);
this->addToolBar(Qt::RightToolBarArea,toolBar2);
// toolBar1->setAllowedAreas();
// toolBar2->setAllowedAreas();
toolBar1->setMovable(true);
toolBar2->setMovable(false);
4. 状态栏(QStatusBar)
状态栏是应用程序中输出简要信息的区域。一般位于主窗口的最底部,一个窗口中最多只能有一个状态栏。在Qt中,状态栏是通过QStatusBar类来实现的。在状态栏中可以显示的消息类型有
- 实时消息:如当前程序状态
- 永久消息:如程序版本号,机构名称
- 进度消息:如进度条提示,百分百提示
4.1. 状态栏的创建
状态栏的创建是通过QMainWindow类提供的statusBar()函数来创建的。
4.2. 在状态栏中显示实时消息
在状态栏中显示实时消息是通过showMessage()函数来实现的,
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QStatusBar *status = this->statusBar();
setStatusBar(status);
QLabel *label = new QLabel("提示信息", this);
status->addWidget(label);
}
‘
调整显示消息的位置
QLabel *label2 = new QLabel("右侧提示信息", this);
status->addPermanentWidget(label2);
5. 浮动窗口(QDocWidget)
在Qt中,浮动窗口也称之为铆接部件。浮动窗口是通过QDockWidget类来实现浮动的功能。浮动窗口一般是位于核心部件的周围,可以有多个。
5.1. 浮动窗口的创建
浮动窗口的创建是通过QDockWidget类提供的构造方法QDockWidget()函数动态创建的;
// 浮动窗口
QDockWidget* dockwidget = new QDockWidget("浮动窗口", this);
// 将浮动窗口置于当前窗口中
addDockWidget(Qt::BottomDockWidgetArea, dockwidget);
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 浮动窗口
QDockWidget* dockwidget = new QDockWidget("浮动窗口", this);
// 将浮动窗口置于当前窗口中
addDockWidget(Qt::BottomDockWidgetArea, dockwidget);
// 浮动窗口也是可以设置标题的
dockwidget->setWindowTitle("这是浮动窗口");
// 给浮动窗口内部,添加一些其他的控件
// 不能直接给这个浮动窗口添加子控件,而是需要创建出一个单独的QWidget,把要添加的控件加入到QWidget中。
// 然后再把这个QWidget设置到dockWidget中
QWidget* container = new QWidget();
dockwidget->setWidget(container);
// 创建布局管理器,把布局管理器设置到QWidget中
QVBoxLayout* layout = new QVBoxLayout;
container->setLayout(layout);
// 创建其他控件添加到layout中
QLabel* label = new QLabel("这是一个QLabel");
QPushButton* btn = new QPushButton("这是按钮");
layout->addWidget(label);
layout->addWidget(btn);
}
5.2. 设置停靠的位置
浮动窗口是位于中心部件的周围。可以通过QDockWidget类中提供setAllowedAreas()函数设置其允许停靠的位置。其中可以设置允许停靠的位置有
Qt::LeftDockWidgetArea --- 停靠在左侧
Qt::RightDockWidgetArea --- 停靠在右侧
Qt::TopDockWidgetArea --- 停靠在顶部
Qt::BottomDockWidgetArea --- 停靠在底部
Qt::AllkWidgetArea --- 四个位置都可以停靠
6. 对话框(QFiledialog,QColorDialog,QFontDialog,QInputDialog,QMessageBox)
对话框是GUI程序中不可缺少的组成部分。一些不适合在主窗口实现的功能组件可以设置在对话框中。对话框通常是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互。Qt常用的内置对话框有:QFiledialog(文件对话框),QColorDialog(颜色对话框),QFontDialog(字体对话框),QInputDialog(输入对话框),QMessageBox(消息框);
6.1. 模态对话框
模态对话框是指:显示后无法与父窗口进行交互,是一种阻塞式的对话框。使用QDialog::exec()函数调用。
模态对话框适用于必须依赖用户选择的场合,比如消息显示,文件选择,打印设置等。
6.1.1. 示例1:创建对话框
要想自定义对话框,就需要继承自QDialog创建类(对话框的内存泄漏问题)
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton(this);
btn->setText("点击创建对话框");
connect(btn,&QPushButton::clicked, this, &MainWindow::push_btn);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::push_btn() {
QDialog* dialog = new QDialog(this);
dialog->setWindowTitle("对话框标题");
// 设置对话框的尺寸
dialog->resize(400, 300);
dialog->exec();
}
6.2. 非模态对话框
非模态对话框显示后独立存在,可以同时与父窗口进行交互,是一种非阻塞式对话框,使用QDialog::show()函数调用。
非模态对话框一般在堆上创建,这是因为如果创建在栈上时,弹出的非模态对话框就会一闪而过。同时还需要设置Qt::WA_DeleteOnClose属性,目的是:当创建多个非模态对话框时,为了避免内存泄漏要设置此属性。
非模态对话框适用于特殊功能设置的场合,比如查找操作,属性设置等。
6.2.1. 示例1:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QTextEdit>
#include <QFileDialog>
#include <QDebug>
#include <fstream>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QDockWidget>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton(this);
btn->setText("点击创建对话框");
connect(btn,&QPushButton::clicked, this, &MainWindow::push_btn);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::push_btn() {
QDialog* dialog = new QDialog(this);
dialog->setWindowTitle("对话框标题");
// 设置对话框的尺寸
dialog->resize(400, 300);
// 通过show党法就可以显示出来对话框
dialog->show();
/*
每次点击都会创建出来一个新的对话框对象,这也就意味着多次点击会产生多个对象,进一步就会产生无数个这样的
对象了。这就会产生内存泄漏。
虽然吧QDialog的父元素设为this了,在进程退出的时候,会由对象树来释放整个对象,但是如果此时在窗口中
点击的多了,(你的机器剩的内存不多了,或者是嵌入式)这就不行了。需要我们手动的把点开的dialog对象给释放了。
*/
// delete dialog; delete放在这里会一闪而过。
// 正确的做法应该是把delete和关闭按钮的点击信号关联起来
// 在用户点击关闭的时候,触发delete
// Qt给QDialog设置了一个属性,可以通过设置属性,来完成上述效果
dialog->setAttribute(Qt::WA_DeleteOnClose);
}
6.3. 消息对话框(QMessageBox)
消息对话框是应用程序中最常用的界面元素。消息对话框主要用于为用户提示重要信息,强制用户进行选择操作。
QMessageBox类中定义了静态成员函数,可以直接调用创建不同风格的消息对话框,其中包括:
Question |
⽤于正常操作过程中的提问 |
Information |
⽤于报告正常运⾏信息 |
Warning |
⽤于报告⾮关键错误 |
Critical |
⽤于报告严重错误 |
6.3.1. 示例1:问题提示消息对话框
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton("消息对话框", this);
QMessageBox* msg = new QMessageBox(this);
msg->setWindowTitle("Warning Message"); // 设置消息对话框的标题
msg->setText("Error Message!"); // 设置消息对话框的内容
msg->setIcon(QMessageBox::Question); // 设置消息对话框的类型
msg->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); // 在消息对话框上设置按钮
connect(btn, &QPushButton::clicked, [=]() {
msg->show();
});
}
其中可以设置的按钮的类型如下
6.4. 颜色对话框(QColorDialog)
颜色对话框的功能是允许用户选择颜色。继承自QDialog类。
常用方法介绍
QColorDialog(QWidget* parent = nullptr) |
创建对象的同时设置父对象 |
QColorDialog(const QColor &initial, QWidget *parent = nullptr) |
创建对象的同时通过QColor对象设置默认颜⾊和⽗对象 |
void setCurrentColor(const QColor &color) |
设置当前颜⾊对话框 |
QColor currentColor() const |
获取当前颜⾊对话框 |
QColor getColor(const QColor &initial = Qt::white, QWidget *parent = nullptr, const QString &title = QString(), QColorDialog::ColorDialogOptions options = ColorDialogOptions()) 参数说明: |
打开颜⾊选择对话框,并返回⼀个QColor对象 |
void open(QObject *receiver, const char *member) |
打开颜⾊对话框 |
6.4.1. 示例1:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton("颜色对话框", this);
QColorDialog* dialog = new QColorDialog(this);
connect(btn, &QPushButton::clicked, [=] {
QColor color = dialog->getColor(QColor(255, 0, 0));
qDebug() << color;
});
}
6.5. 文件对话框(QFileDialog)
文件对话框用于应用程序需要打开一个外部文件或需要将当前内容存储到指定的外部文件。
打开文件 |
QString getOpenFileName( |
打开多个文件 |
QStringList getOpenFileNames( |
保存文件 |
QString getSaveFileName( |
6.5.1. 示例1:打开文件
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton("文件", this);
QFileDialog* file = new QFileDialog(this);
connect(btn, &QPushButton::clicked, [=] {
QString str = file->getOpenFileName(this,
"file",
"C:\\Users\\Lenovo\\Desktop\\2024-03-26"
);
});
}
6.6. 字体对话框(QFontDialog)
Qt中提供了预定义的字体对话框类QFontDialog,用于提供选择字体的对话框部件
6.6.1. 示例1:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton("文件", this);
connect(btn, &QPushButton::clicked, [=] {
bool flag;
QFont font = QFontDialog::getFont(&flag, QFont("华文行楷", 36));
// 将char* 转换为QString 的方法, toUtf8().data();
qDebug() << "字体:" << font.family().toUtf8().data();
// pointSize() 获取字号
qDebug() << "字号:" << font.pointSize();
// bold() --- 判断字体是否加粗
qDebug() << "是否加粗:" << font.bold();
// italic() ---- 判断字体是否倾斜
qDebug() << "是否倾斜:" << font.italic();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
6.7. 输入对话框(QInputDialog)
Qt中提供了预定义的输入对话框类:QInputDialog,用于进行临时数据输入的场合
双精度浮点型输⼊数据对话框 |
double getDouble ( |
整型输⼊数据对话框 |
int getInt ( |
选择条⽬型输⼊数据框 |
QString getItem ( |
参数说明: |
parent:⽗亲 |
6.7.1. 示例1:浮点型数据输入对话框
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPushButton* btn = new QPushButton("输入框", this);
QInputDialog* input = new QInputDialog(this);
connect(btn, &QPushButton::clicked, [=] {
double d = input->getDouble(this, "输入框", "浮点型");
qDebug() << d;
});
}
MainWindow::~MainWindow()
{
delete ui;
}
7. 小结
- 菜单栏(QMenuBar)=>菜单(QMenu)=>菜单项(QAciton)
- 工具栏(QToolBar)(具有多个)=>菜单项(QAction)
- 子窗口(QDockWidget)=>QWidget=>放置其他的控件
- 状态栏(QStatusBar)=>QWidget
- 对话框(QDialog)=>自己手动继承的方式,针对QDialog进行扩展