1. Qt 窗口概述
(1)Qt 窗口 是通过 QMainWindow类 来实现的。
- QMainWindow 是一个为用户提供主窗口程序的类,继承自 QWidget 类,并且提供了⼀个预定义的布局。
- QMainWindow 包含 一个菜单栏(menu bar)、多个工具栏(tool bars)、多个浮动窗口(铆接部件)(dock widgets)、一个状态栏(status bar) 和一个 中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。如下图为 QMainwindow 中 各组件所处的位置:
2. 菜单栏
(1)Qt 中的菜单栏是通过 QMenuBar 这个类来实现的。⼀个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。
- 菜单栏中包含菜单。菜单中包含菜单项。
2.1 创建菜单栏
(1)方式一:菜单栏的创建可以借助于 QMainWindow类 提供的 menuBar() 函数来实现。menubar()函数原型如下:
QMenuBar* menuBar() const
(2)方式二:在堆上动态创建;
- 使用 setMenuBar 把菜单栏放到窗口中。
2.2 在菜单栏中添加菜单
(1)创建菜单,并通过 QMenu 提供的 addMenu() 函数 来添加菜单。 示例如下:
2.3 创建菜单项
(1)在 Qt 中,并没有专门的菜单项类,可以通过 QAction 类,抽象出公共的动作。如在菜单中添加菜单项。
- QAction 可以给菜单栏使用,也可以给工具栏使用。
- 示例如下:
2.4 在菜单项之间添加分割线
(1)在菜单项之间可以添加分割线。分割线如下图所示,添加分割线是通过 QMenu 类 提供的 addSeparator() 函数来实现;
(2)示例如下:
2.5 综合示例
(1)在窗口上创建一个菜单栏,在菜单栏中添加一些菜单,在某一个菜单中添加一些菜单项。
- 新建 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);
// 创建中央控件
edit = new QTextEdit(this);
this->setCentralWidget(edit);
edit->setPlaceholderText("此处编写⽂本内容...");
}
- 给 action 添加⼀些动作:
// 连接信号槽, 点击 action 时触发⼀定的效果.
connect(action1, &QAction::triggered, this, &MainWindow::save);
connect(action2, &QAction::triggered, this, &MainWindow::load);
- 实现这两个槽函数:
- 使用 QFileDialog 来实现选择文件的效果。
- getSaveFileName 用于保存文件的场景。此时的对话框可以输入文件名。
- getOpenFileName 用于打开文件的场景。此时的对话框可以获取到鼠标选择的文件名。
- 搭配 C++ 标准库的文件操作实现文件读写。
- 使用 QFileDialog 来实现选择文件的效果。
void MainWindow::save()
{
// 弹出对话框, 选择写⼊⽂件的路径
QFileDialog* dialog = new QFileDialog(this);
QString fileName = dialog->getSaveFileName(this, "保存⽂件", "C:/Users/1/");
qDebug() << "fileName: " << fileName;
// 写⼊⽂件
std::ofstream file(fileName.toStdString().c_str());
if (!file.is_open())
{
qDebug() << "⽂件保存失败!";
return;
}
const QString& text = edit->toPlainText();
file << text.toStdString();
file.close();
}
void MainWindow::load()
{
// 弹出对话框, 选择打开的⽂件
QFileDialog* dialog = new QFileDialog(this);
QString fileName = dialog->getOpenFileName(this, "加载⽂件", "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. 工具栏
(1)工具栏是应用程序中集成各种功能实现快捷键使用的⼀个区域。可以有多个,也可以没有,它并不是应用程序中必须存在的组件。它是一个可移动的组件,它的元素可以是各种窗口组件,它的元素通常以图标按钮的方式存在。如下图为工具栏的示意图:
3.1 创建工具栏
(1)调用 QMainWindow类 的 addToolBar() 函数来创建工具栏,每增加一个工具栏都需要调用一次该函数。
- 如添加两个工具栏:
3.2 设置停靠位置
(1)工具栏停靠位置的设置有两种方式。一种是在创建工具栏的同时指定停靠的位置,另一种是通过QToolBar类 提供的 setAllowedAreas()函数 来设置。
- 方式一:创建工具栏的同时指定其停靠的位置。
- 在创建工具栏的同时,也可以设置工具栏的位置,其默认位置是在窗口的最上面;如上述代码,默认在最上面显示。工具栏允许停靠的区域由 QToolBar类 提供的 allowAreas()函数 决定,其中可以设置的位置包括:
- Qt::LeftToolBarArea:停靠在左侧。
- Qt::RightToolBarArea:停靠在右侧。
- Qt::TopToolBarArea:停靠在顶部。
- Qt::BottomToolBarArea:停靠在底部。
- Qt::AllToolBarAreas:以上四个位置都可停靠。
- 示例:
- 方式二:使用 QToolBar类 提供的 setAllowedAreas()函数 设置停靠位置。如下示例:
(2)说明:
- 在创建工具栏的同时指定其停靠的位置,指的是程序运行时工具栏默认所在的位置;而使用 setAllowedAreas()函数设置停靠位置,指的是工具栏允许其所能停靠的位置。
3.3 设置浮动属性
(1)工具栏的浮动属性可以通过 QToolBar类 提供的 setFloatable()函数 来设置。setFloatable()函数原型为:
void setFloatable (bool floatable);
- 参数:
- true:浮动。
- false:不浮动。
- 示例:
3.4 设置移动属性
(1)设置工具栏的移动属性可以通过 QToolBar类 提供的 setMovable()函数 来设置。setMovable()函数 原型为:
void setMovable(bool movable);
- 参数:
- true:移动。
- false:不移动。
- 示例:
(2)说明:
- 若设置工具栏为不移动状态,则设置其停靠位置的操作就不会生效,所以设置工具栏的移动属性类似于总开关的效果。
3.5 综合示例
(1)综合代码如下:
4. 状态栏
(1)状态栏是应用程序中输出简要信息的区域。一般位于主窗口的最底部,一个窗口中最多只能有一个状态栏。在 Qt 中,状态栏是通过 QStatusBar类 来实现的。 在状态栏中可以显示的消息类型有:
- 实时消息:如当前程序状态。
- 永久消息:如程序版本号,机构名称。
- 进度消息:如进度条提示,百分百提示。
4.1 状态栏的创建
(1)状态栏的创建是通过 QMainWindow 类 提供的 statusBar() 函数来创建;示例如下:
4.2 在状态栏中显示实时消息
(1)在状态栏中显示实时消息是通过 showMessage() 函数来实现,示例如下:
4.3 在状态栏中显示永久消息
(1)在状态栏中可以显示永久消息,此处的永久消息是通过标签来显示的;示例如下:
(2)显示效果如下:
(3)调整显示消息的位置:
(4)显示效果如下:
5. 浮动窗口
(1)在 Qt 中,浮动窗口也称之为铆接部件。浮动窗口是通过 QDockWidget类 来实现浮动的功能。浮动窗口一般是位于核心部件的周围,可以有多个。
5.1 浮动窗口的创建
(1)浮动窗口的创建是通过 QDockWidget类 提供的构造方法 QDockWidget()函数 动态创建的;示例如下:
5.2 设置停靠的位置
(1)浮动窗口是位于中心部件的周围。可以通过 QDockWidget类 中提供setAllowedAreas() 函数设置其允许停靠的位置。其中可以设置允许停靠的位置有:
- Qt::LeftDockWidgetArea:停靠在左侧。
- Qt::RightDockWidgetArea:停靠在右侧。
- Qt::TopDockWidgetArea:停靠在顶部。
- Qt::BottomDockWidgetArea:停靠在底部。
- Qt::AllDockWidgetAreas:以上四个位置都可停靠。
(2)示例如下:设置浮动窗口只允许上下停靠。
6. 对话框
(1)对话框是 GUI 程序中不可或缺的组成部分。一些不适合在主窗口实现的功能组件可以设置在对话框中。对话框通常是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互。
- Qt常用的内置对话框有:QFiledialog(文件对话框)、QColorDialog(颜色对话框)、QFontDialog(字体对话框)、QInputDialog (输入对话框)和 QMessageBox(消息框) 。
6.1 对话框的分类
(1)对话框分为 模态对话框 和 非模态对话框。
6.1.1 模态对话框
(1)模态对话框指的是:显示后无法与父窗口进行交互,是一种阻塞式的对话框。使用 QDialog::exec() 函数 调用。
- 模态对话框适用于必须依赖用户选择的场合,比如消息显示,文件选择,打印设置等。
(2)示例:
- 新建 Qt 项目,在 ui 文件中的菜单栏中设置两个菜单:“文件” 和 “编辑”,在 菜单 “文件” 下新建菜单项:“创建” 并将菜单项 “新建” 置于工具栏中 ; 如下图示:
- 在 mainwindow.cpp 文件中实现:当点击 “新建” 时,弹出⼀个模态对话框;
- 说明:在菜单项中,点击菜单项时就会触发 triggered() 信号。
6.1.2 非模态对话框
(1)非模态对话框显示后独立存在,可以同时与父窗口进行交互,是一种非阻塞式对话框,使用QDialog::show()函数调用。
- 非模态对话框⼀般在堆上创建,这是因为如果创建在栈上时,弹出的非模态对话框就会⼀闪而过。同时还需要设置 Qt:WA_DeleteOnClose 属性,目的是:当创建多个非模态对话框时(如打开了多个非模态窗口),为了避免内存泄漏要设置此属性。
- 非模态对话框适用于特殊功能设置的场合,比如查找操作,属性设置等。
(2)示例:
6.1.3 混合属性对话框
(1)混合属性对话框同时具有模态对话框和非模态对话框的属性,对话框的生成和销毁具有非模态对话框属性,功能上具有模态对话框的属性。
- 使用 QDialog::setModal() 函数 可以创建混合特性的对话框。通常,创建对话框时需要指定对话框的父组件。
(2)示例:
6.2 Qt 内置对话框
(1)Qt 提供了多种可复用的对话框类型,即 Qt 标准对话框。Qt 标准对话框全部继承于 QDialog类。常用标准对话框如下:
6.2.1 消息对话框 QMessageBox
(1)消息对话框是应用程序中最常用的界面元素。消息对话框主要用于为用户提示重要信息,强制用户进行选择操作。
- QMessageBox类 中定义了静态成员函数,可以直接调用创建不同风格的消息对话框,其中包括:
消息类型 | 说明 |
---|---|
Question | 用于正常操作过程中的提问。 |
Information | 用于报告正常运行信息。 |
Warning | 用于报告非关键错误。 |
Critical | 用于报告严重错误。 |
(2)其对应的函数原型如下:
(3)示例1:问题提示消息对话框。
- 实现效果如下:
- 其中可以设置的按钮的类型如下:
- 更改消息对话框中的按钮类型:
- 实现效果如下:
(4)示例2:信息提示消息对话框。
- 实现效果如下:
(5)示例3:警告信息消息对话框。
- 实现效果如下:
(6)示例4:错误提示消息对话框。
- 实现效果如下:
6.2.2 颜色对话框 QColorDialog
(1)颜色对话框的功能是允许用户选择颜色。继承自 QDialog 类。颜色对话框如下图示:
(2)常用方法介绍:
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) //打开颜色对话框
- 参数说明:
- initial:设置默认颜色。
- parent:设置父对象。
- title:设置对话框标题。
- options:设置选项。
(3)示例1:
- 效果如下:
(4)示例2:
- 效果如下:
6.2.3 文件对话框 QFileDialog
(1)文件对话框用于应用程序中需要打开一个外部文件或需要将当前内容存储到指定的外部文件。常用方法介绍:
- 打开文件(一次只能打开一个文件)。
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());
- 参数说明:
- parent:父亲。
- caption:对话框标题。
- dir:默认打开的路径。
- filter:文件过滤器。
(2)示例1:打开文件。
- 运行效果:
(3)示例2:保存文件。
6.2.4 字体对话框 QFontDialog
(1)Qt 中提供了预定义的字体对话框类 QFontDialog,用于提供选择字体的对话框部件。示例如下:
- 运行效果如下:
6.2.5 输入对话框 QInputDialog
(1)Qt 中提供了预定义的输入对话框类:QInputDialog,用于进行临时数据输入的场合。 常用方法介绍:
- 双精度浮点型输⼊数据对话框。
double getDouble (QWidget *parent, const QString &title, const QString &label, double value = 0, double min = -2147483647, double max = 2147483647, int decimals = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
- 整型输入数据对话框。
int getInt (QWidget *parent, const QString &title, const QString &label, int value = 0, int min = -2147483647, int max = 2147483647, int step = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
- 选择条目型输入数据框。
QString getItem (QWidget *parent, const QString &title, const QString &label, const QStringList &items, int current = 0, bool editable = true, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(), Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
- 参数说明:
- parent:父亲。
- title:对话框标题。
- label:对话框标签。
- items:可供选择的条目。
(2)示例1:浮点型数据输入对话框。
- 运行效果:
(3)示例2:整型数据输入对话框。
- 运行效果:
(4)示例3:打开选择条目对话框。
- 运行效果如下:
7. Qt 窗口总结
(1)窗口类型与核心类:
- QWidget:
- 功能:所有窗口部件的基类,可作为独立窗口或嵌入其他窗口。
- 关键方法:
QWidget window;
window.setWindowTitle("窗口标题");
window.resize(400, 300);
window.show();
- QMainWindow:
- 功能:主窗口框架,包含菜单栏、工具栏、状态栏、中心部件和停靠窗口。
- 典型结构:
QMainWindow mainWindow;
mainWindow.setMenuBar(menuBar);
mainWindow.setCentralWidget(centralWidget);
mainWindow.addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
- QDialog:
- 功能:对话框基类,用于短期用户交互(如确认框、文件选择)。
- 模态与非模态:
QDialog dialog;
dialog.exec(); // 模态对话框(阻塞父窗口)
dialog.show(); // 非模态对话框
- QMdiArea:
- 功能:多文档界面(MDI)容器,管理多个子窗口(QMdiSubWindow)。
- 示例:
QMdiArea mdiArea;
QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
subWindow->setWindowTitle("子窗口");
(2)窗口属性与操作:
- 窗口标题与图标:
window.setWindowTitle("应用程序");
window.setWindowIcon(QIcon(":/app_icon.png"));
- 窗口尺寸与位置
window.setGeometry(100, 100, 800, 600); // x, y, width, height
window.move(200, 200); // 移动窗口
window.resize(1024, 768); // 调整窗口大小
- 窗口状态:
window.showMaximized(); // 最大化
window.showMinimized(); // 最小化
window.showFullScreen(); // 全屏
window.showNormal(); // 恢复默认
- 窗口标志(Window Flags):
// 无边框窗口
window.setWindowFlags(Qt::FramelessWindowHint);
// 置顶窗口
window.setWindowFlags(window.windowFlags() | Qt::WindowStaysOnTopHint);
(3)窗口事件处理:
- 重写事件方法:
class MyWidget : public QWidget {
protected:
void closeEvent(QCloseEvent *event) override
{
if (unsavedChanges)
{
event->ignore(); // 阻止关闭
}
else
{
event->accept();
}
}
void resizeEvent(QResizeEvent *event) override
{
qDebug() << "窗口大小已改变:" << event->size();
}
};
- 常用事件:
- mousePressEvent():鼠标按下。
- keyPressEvent():键盘按键。
- paintEvent():窗口绘制。
(4)窗口布局管理:
- 在 QMainWindow 中使用布局:
QMainWindow mainWindow;
QWidget *centralWidget = new QWidget(&mainWindow);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
layout->addWidget(new QPushButton("按钮"));
mainWindow.setCentralWidget(centralWidget);
- 嵌套布局示例:
QWidget *widget = new QWidget;
QHBoxLayout *hLayout = new QHBoxLayout(widget);
hLayout->addWidget(new QLineEdit);
hLayout->addWidget(new QPushButton("提交"));
(5)对话框与窗口通信:
- 自定义对话框:
class MyDialog : public QDialog {
public:
MyDialog(QWidget *parent = nullptr) : QDialog(parent)
{
QPushButton *btn = new QPushButton("确定", this);
connect(btn, &QPushButton::clicked, this, &QDialog::accept);
}
};
- 信号传递:
// 主窗口接收子窗口信号
MyDialog dialog;
connect(&dialog, &MyDialog::dataReady, this, &MainWindow::handleData);
(6)窗口样式与外观:
- 样式表(QSS):
window.setStyleSheet("QWidget { background: #f0f0f0; }");
- 调色板(QPalette):
QPalette palette;
palette.setColor(QPalette::Window, Qt::lightGray);
window.setPalette(palette);
(7)窗口生命周期与内存管理:
- 父子关系:
QWidget *child = new QWidget(parent); // parent 析构时自动释放 child
- 动态窗口释放:
QDialog *dialog = new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose); // 关闭时自动删除
dialog->show();