目录
引言:
Qt 窗口 是通过 QMainWindow类 来实现的。
QMainWindow 是⼀个为用户提供主窗口程序的类,继承自 QWidget 类,并且提供了一个预定义的布局。QMainWindow 包含 一个菜单栏(menu bar)、多个工具栏(tool bars)【工具栏本质上就是把菜单栏中的一些比较常用的选项,直接放到工具栏里了,直接点击工具栏中的按钮就能快速生效】、多个浮动窗口(铆接部件)(dock widgets)、一个状态栏(status bar) 和一个 中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。如下图为 QMainwindow 中 各组件所处的位置:
1. 菜单栏
Qt 中的菜单栏是通过 QMenuBar 这个类来实现的。一个主窗口最多只有一个菜单栏。位于主窗口顶部、主窗口标题栏下面。
菜单栏中包含菜单. 菜单中包含菜单项.
1.1 创建菜单栏
方式一 :菜单栏的创建可以借助于 QMainWindow类 提供的 menuBar() 函数来实现。
- menubar()函数原型如下:
QMenuBar * menuBar() const
// 创建菜单栏
QMenuBar* menubar = menuBar();
// 将菜单栏放入窗口中
this->setMenuBar(menubar);
方式二:在堆上动态创建;
- 使用 setMenuBar 把菜单栏放到窗口中.
// 创建菜单栏
QMenuBar* menubar = new QMenuBar(this);
// 将菜单栏放入窗口中
this->setMenuBar(menubar);
1.2 在菜单栏中添加菜单
创建菜单,并通过 QMenu 提供的 addMenu() 函数 来添加菜单。
示例:
// 创建菜单栏
QMenuBar* menubar = new QMenuBar();
// 将菜单栏放入窗口中
this->setMenuBar(menubar);
// 创建菜单
QMenu* menu1 = new QMenu("文件");
QMenu* menu2 = new QMenu("编辑");
QMenu* menu3 = new QMenu("视图");
// 添加菜单到菜单栏中
menubar->addMenu(menu1);
menubar->addMenu(menu2);
menubar->addMenu(menu3);
1.3 创建菜单项
在 Qt 中,并没有专门的菜单项类,可以通过 QAction 类,抽象出公共的动作。如在菜单中添加菜单项.
🌴QAction 可以给菜单栏使用, 也可以给工具栏使用.
示例:
// 创建菜单项
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);
1.4 在菜单项之间添加分割线
在菜单项之间可以添加分割线。分割线如下图所示,添加分割线是通过 QMenu 类 提供的 addSeparator() 函数来实现;
示例:
// 创建菜单项
QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("打开");
QAction* action3 = new QAction("保存");
QAction* action4 = new QAction("另存为");
QAction* action5 = new QAction("退出");
// 将菜单添加到菜单上
menu1->addAction(action1);
menu1->addSeparator();// 在 “新建” 和 “打开” 中间添加分割线
menu1->addAction(action2);
menu1->addAction(action3);
menu1->addAction(action4);
menu1->addAction(action5);
1.5 综合示例
在窗口上创建一个菜单栏,在菜单栏中添加一些菜单,在某一个菜单中添加一些菜单项。
1、新建 Qt 项目
- 注意:此时新建项目时选择的基类 QMainwindow ,如下图示:
2、在 "mainwindow.cpp" 文件中创建菜单和中央控件
- 创建一个菜单栏, 一个菜单.
- 两个菜单项: 保存, 加载
- 创建一个 QTextEdit 作为窗口的中央控件.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 设置标题
this->setWindowTitle("我的记事本");
// 创建菜单栏
QMenuBar* menubar = this->menuBar();
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("此处编写文本内容...");
}
3、给 action 添加一些动作
// 连接信号槽,点击 action 时触发一定的效果
connect(action1, &QAction::triggered, this, &MainWindow::save);
connect(action2, &QAction::triggered, this, &MainWindow::load);
实现这两个槽函数
a. 使用 QFileDialog 来实现选择文件的效果.
- getSaveFileName 用于保存文件的场景. 此时的对话框可以输入文件名.
- getOpenFileName 用于打开文件的场景. 此时的对话框可以获取到鼠标选择的文件名.
b. 搭配 C++ 标准库的文件操作实现文件读写.
void MainWindow::save()
{
// 弹出对话框, 选择写⼊⽂件的路径
QFileDialog* dialog = new QFileDialog(this);
QString fileName = dialog->getSaveFileName(this, "保存⽂件", "D:/");
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, "加载⽂件", "D:/");
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);
}
4、执行程序, 此时就可以通过程序来保存/加载文件了. 并且对文件进行编辑.
2.工具栏
工具栏是应用程序中集成各种功能实现快捷键使用的一个区域。可以有多个,也可以没有,它并不是应用程序中必须存在的组件。它是一个可移动的组件,它的元素可以是各种窗口组件,它的元素通常以图标按钮的方式存在。如下图为工具栏的示意图:
2.1 创建工具栏
调用 QMainWindow类 的 addToolBar() 函数来创建工具栏,每增加一个工具栏都需要调用一次该函数。
代码示例:
1.编写 mainwindow.cpp,在构造函数中编写初始化代码
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 工具栏需要手动创建出来,自身不会创建
QToolBar* toolbar = new QToolBar();
this->addToolBar(toolbar);
QAction* action1 = new QAction("保存");
QAction* action2 = new QAction("退出");
toolbar->addAction(action1);
toolbar->addAction(action2);
connect(action1, &QAction::triggered, this, &MainWindow::save);
connect(action2, &QAction::triggered, this, &MainWindow::exit);
}
注意:
- 添加菜单栏,使用的是 setMenuBar,这是因为菜单栏只能有一个,重复设置,就会新的替换旧的(set 就包含了 “替换”)。
- 添加工具栏,使用的是 addToolBar,这是因为工具栏可以有多个,重复设置,就会出现多个工具栏,不包含 “替换”。
2.给工具栏的快捷项设置 slot 函数
void MainWindow::save()
{
qDebug() << "save";
}
void MainWindow::exit()
{
qDebug() << "exit";
}
3.执行程序,观察效果
4.工具栏展示的一般是图标,而不是文本,所以我们给它设置成图标(使用 qrc 机制)
QAction* action1 = new QAction("保存");
QAction* action2 = new QAction("退出");
action1->setIcon(QIcon(":/save.png"));
action2->setIcon(QIcon(":/exit.png"));
toolbar->addAction(action1);
toolbar->addAction(action2);
注意:
QAction 如果出现在工具栏上,也会产生 图标 覆盖文本 这样的情况,但是,当我们将文本替换成图标后,之前设置的文本会以 toolTip 的方式来存在,当鼠标悬停上去的时候,就会显示出一段提示信息,另外,我们也可以手动设置这里的 toolTip~
action1->setToolTip("点击这里保存文件");
5.工具栏往往也是和菜单栏搭配使用的,即工具栏中的 QAction 也可以出现在菜单中
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);
// 创建两个菜单项
QAction* action1 = new QAction("保存");
QAction* action2 = new QAction("退出");
// action1->setToolTip("点击这里保存文件");
action1->setIcon(QIcon(":/save.png"));
action2->setIcon(QIcon(":/exit.png"));
// 菜单项放到工具栏中
toolbar->addAction(action1);
toolbar->addAction(action2);
// 菜单项放在菜单中
menu->addAction(action1);
menu->addAction(action2);
}
2.2 设置停靠位置
工具栏停靠位置的设置有两种方式。一种是在创建工具栏的同时指定停靠的位置,另一种是通过QToolBar类 提供的 setAllowedAreas()函数 来设置。
🍒方式一:创建工具栏的同时指定其停靠的位置。
在创建工具栏的同时,也可以设置工具栏的位置,其默认位置是在窗口的最上面;如上述代码,默认在最上面显示。工具栏允许停靠的区域由 QToolBar类 提供的 allowAreas()函数 决定,其中可以设置的位置包括:
- Qt::LeftToolBarArea 停靠在左侧
- Qt::RightToolBarArea 停靠在右侧
- Qt::TopToolBarArea 停靠在顶部
- Qt::BottomToolBarArea 停靠在底部
- Qt::AllToolBarAreas 以上四个位置都可停靠
代码示例:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 创建工具栏
QToolBar* toolBar1 = new QToolBar();
QToolBar* toolBar2 = new QToolBar();
// 创建工具栏的同时,指定工具栏在左侧显示
this->addToolBar(Qt::LeftToolBarArea, toolBar1);
// 创建工具栏的同时,指定工具栏在右侧显示
this->addToolBar(Qt::RightToolBarArea, toolBar2);
QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("打开");
QAction* action3 = new QAction("关闭");
QAction* action4 = new QAction("保存");
toolBar1->addAction(action1);
toolBar1->addAction(action2);
toolBar2->addAction(action3);
toolBar2->addAction(action4);
}
🍒方式二:使用 QToolBar类 提供的 setAllowedAreas()函数 设置停靠位置。
代码示例:
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(toolBar2);
// 只允许在顶部停靠
toolBar1->setAllowedAreas(Qt::TopToolBarArea);
// 只允许在底部停靠
toolBar2->setAllowedAreas(Qt::BottomToolBarArea);
QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("打开");
QAction* action3 = new QAction("关闭");
QAction* action4 = new QAction("保存");
toolBar1->addAction(action1);
toolBar1->addAction(action2);
toolBar2->addAction(action3);
toolBar2->addAction(action4);
}
说明:
在创建工具栏的同时指定其停靠的位置,指的是程序运行时工具栏默认所在的位置;而使用setAllowedAreas()函数设置停靠位置,指的是工具栏允许其所能停靠的位置。
2.3 设置浮动属性
工具栏的浮动属性可以通过 QToolBar类 提供的 setFloatable()函数 来设置。
setFloatable()函数原型为:
- void setFloatable (bool floatable)
参数:
- true:浮动
- false:不浮动
代码示例:
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(toolBar2);
// 只允许在顶部停靠
toolBar1->setAllowedAreas(Qt::TopToolBarArea);
// 只允许在底部停靠
toolBar2->setAllowedAreas(Qt::BottomToolBarArea);
toolBar1->setFloatable(true);// 允许工具栏浮动
toolBar2->setFloatable(false);// 不允许工具栏浮动
QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("打开");
QAction* action3 = new QAction("关闭");
QAction* action4 = new QAction("保存");
toolBar1->addAction(action1);
toolBar1->addAction(action2);
toolBar2->addAction(action3);
toolBar2->addAction(action4);
}
2.4 设置移动属性
设置工具栏的移动属性可以通过 QToolBar类 提供的 setMovable()函数 来设置。
setMovable()函数 原型为
- void setMovable(bool movable)
参数:
- true:移动
- false:不移动
说明:
- 若设置工具栏为不移动状态,则设置其停靠位置的操作就不会生效,所以设置工具栏的移动属性类似于总开关的效果。
代码示例:
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(toolBar2);
// 只允许在顶部停靠
toolBar1->setAllowedAreas(Qt::TopToolBarArea);
// 只允许在底部停靠
toolBar2->setAllowedAreas(Qt::BottomToolBarArea);
toolBar1->setFloatable(true);// 允许工具栏浮动
toolBar2->setFloatable(false);// 不允许工具栏浮动
toolBar1->setMovable(true);// 允许移动
toolBar2->setMovable(false);// 不允许移动
QAction* action1 = new QAction("新建");
QAction* action2 = new QAction("打开");
QAction* action3 = new QAction("关闭");
QAction* action4 = new QAction("保存");
toolBar1->addAction(action1);
toolBar1->addAction(action2);
toolBar2->addAction(action3);
toolBar2->addAction(action4);
}
3. 状态栏
状态栏是应用程序中输出简要信息的区域。一般位于主窗口的最底部,一个窗口中最多只能有一个状态栏。在 Qt 中,状态栏是通过 QStatusBar类 来实现的。 在状态栏中可以显示的消息类型有:
- 实时消息:如当前程序状态
- 永久消息:如程序版本号,机构名称
- 进度消息:如进度条提示,百分百提示
3.1 状态栏的创建
状态栏的创建是通过 QMainWindow 类 提供的 statusBar() 函数来创建;
代码示例:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 存在就获取,不存在就创建
QStatusBar* statusBar = this->statusBar();
// 如果状态栏没有被创建,这样的设置是必要的
// 如果状态栏已经在窗口中存在,这样的设置其实意义不大,但也没副作用,仍然保留
this->setStatusBar(statusBar);
}
3.2 在状态栏中显示实时消息
在状态栏中显示实时消息是通过 showMessage() 函数来实现。
通过 showMessage 可以在状态栏中显示一个文本,此时这个文本存在的时间可以自定义。timeOut 参数是一个单位为 ms 的时间,如果 timeOut 为 0(不填),消息就会持久存在。
代码示例:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 存在就获取,不存在就创建
QStatusBar* statusBar = this->statusBar();
// 如果状态栏没有被创建,这样的设置是必要的
// 如果状态栏已经在窗口中存在,这样的设置其实意义不大,但也没副作用,仍然保留
this->setStatusBar(statusBar);
// 状态栏中显示大约 3秒 的“Hello Qt”
statusBar->showMessage("Hello Qt", 3000);
}
3.3 在状态栏中显示永久消息
在状态栏中可以显示永久消息,此处的永久消息是通过 标签 来显示的,也可以添加其它控件。
代码示例:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 存在就获取,不存在就创建
QStatusBar* statusBar = this->statusBar();
// 如果状态栏没有被创建,这样的设置是必要的
// 如果状态栏已经在窗口中存在,这样的设置其实意义不大,但也没副作用,仍然保留
this->setStatusBar(statusBar);
// 创建标签
QLabel* label = new QLabel("提示信息");
// 将标签放入状态栏中
statusBar->addWidget(label);
// 创建进度条并将进度条放入状态栏中
QProgressBar* progressBar = new QProgressBar();
progressBar->setRange(0, 100);
progressBar->setValue(50);
statusBar->addWidget(progressBar);
}
显示效果如下:
调整显示消息的位置:
QPushButton* button = new QPushButton("按钮");
statusBar->addPermanentWidget(button);
显示效果如下:
4. 浮动窗口
在 Qt 中,浮动窗口也称之为铆接部件。浮动窗口是通过 QDockWidget类 来实现浮动的功能。浮动窗口一般是位于核心部件的周围,可以有多个。
4.1 浮动窗口的创建
浮动窗口的创建是通过 QDockWidget类 提供的构造方法 QDockWidget()函数 动态创建的;
代码示例:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 浮动窗口
QDockWidget* dockWidget = new QDockWidget();
// 将浮动窗口置于当前窗口中
this->addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
// 给浮动窗口设置标题
dockWidget->setWindowTitle("浮动窗口");
// 给浮动窗口内部添加一些其它的控件
// 不能直接给这个浮动窗口添加子控件,而是需要创建出一个单独的 QWidget,把要添加的控件加入到 QWidget 中
// 然后再把这个 QWidget 设置到 dockWidget 中
QWidget* container = new QWidget();
dockWidget->setWidget(container);
// 创建布局管理器,把布局管理器设置到 QWidget 中
QVBoxLayout* vlayout = new QVBoxLayout();
container->setLayout(vlayout);
// 创建其它控件添加到 layout 中
QLabel* label = new QLabel("标签");
QPushButton* button = new QPushButton("按钮");
vlayout->addWidget(label);
vlayout->addWidget(button);
}
4.2 设置停靠的位置
浮动窗口是位于中心部件的周围。可以通过 QDockWidget类 中提供 setAllowedAreas() 函数设置其允许停靠的位置。其中可以设置允许停靠的位置有:
- Qt::LeftDockWidgetArea 停靠在左侧
- Qt::RightDockWidgetArea 停靠在右侧
- Qt::TopDockWidgetArea 停靠在顶部
- Qt::BottomDockWidgetArea 停靠在底部
- Qt::AllDockWidgetAreas 以上四个位置都可停靠
示例如下:设置浮动窗口只允许上下停靠
// 设置浮动窗口的区域,只允许上下停靠
dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);