文章目录
- 创建菜单栏
- 创建菜单并在菜单栏中添加
- 创建子菜单并添加到菜单
- 创建菜单项并在菜单中添加
- 分割线
- 实现简易的记事本
Qt 窗口是通过 QMainWindow类 来实现的
创建菜单栏
Qt 中的菜单栏是通过 QMenuBar 这个类来实现的,一个窗口最多只有一个菜单栏。
菜单栏包含了菜单,而菜单又包含了菜单项
上图可以看出,菜单里面不只是可以包含菜单项,也可以包含菜单,这种被菜单包含的菜单成为子菜单
可以有两种方式创建菜单栏:
QMenuBar *menuBar = new QMenuBar();
this->setMenuBar(menuBar);
QMenuBar *menuBar = this->menuBar();
this->setMenuBar(menuBar);
对于菜单栏而言,在QMainWindow类对象被创建出来时默认是自动生成了一个菜单栏的。
因此对于第一种方式而言:通过重新new出来一个 QMenuBar 对象再赋值给 this,这种方式就会导致 this 默认自动生成的菜单栏被挤出对象树,这种情况就会导致找不到默认的菜单栏从而无法释放。虽然对于客户端而言这一点点的泄漏问题可以不会很大,但是还是做到尽量完美。
对于第二种方式而言:this->menuBar() 会有两种情况:当 this 没有菜单栏时会自动生成一个菜单栏;当 this 有菜单栏时就获取已有的菜单栏。所以第二种方式就不会多生成出额外的菜单栏对象,也就不会出现内存泄漏的情况。
创建菜单并在菜单栏中添加
菜单的类型为 QMenu,菜单栏通过 addMenu 函数去添加菜单
// 创建菜单
// (&?):设置快捷键(?可以是任一字母)
// 菜单的快捷键需要搭配 alt 键使用
QMenu *m1 = new QMenu("文件(&F)");
QMenu *m2 = new QMenu("编辑(&E)");
QMenu *m3 = new QMenu("构建(&B)");
// 将菜单加到菜单栏
menuBar->addMenu(m1);
menuBar->addMenu(m2);
menuBar->addMenu(m3);
创建子菜单并添加到菜单
添加子菜单的方式:先创建出需要的子菜单(子菜单也是菜单,也是 QMenu 类型),然后菜单可以通过 addMenu 函数添加子菜单。
// 创建子菜单
QMenu *c1 = new QMenu("最近打开文件");
// 将子菜单加到菜单
m1->addMenu(c1);
创建菜单项并在菜单中添加
在 Qt 中并没有专门的菜单项类,可以通过 QAction 类抽象出公共的动作。
菜单项也可以为自己添加图标,setIcon(QIcon *)
// 创建菜单项
QAction *a1 = new QAction("打开(&O)");
QAction *a2 = new QAction("另存为(&A)");
a2->setIcon(QIcon(":/img/save.png")); // 给菜单项设置图标
QAction *a3 = new QAction("清除菜单");
// 将菜单项加到菜单
m1->addAction(a1);
m1->addAction(a2);
c1->addAction(a3);
分割线
菜单项之间可以添加分割线,子菜单之间也可以添加分割线。
通过菜单调用 addSeparator 函数
// 将菜单项加到菜单
m1->addAction(a1);
m1->addSeparator(); // 添加分割线
m1->addAction(a2);
c1->addAction(a3);
// 将子菜单加到菜单
m1->addMenu(c1);
m1->addSeparator(); // 添加分割线
m1->addMenu(c2);
实现简易的记事本
用到了 QFileDialog 类来实现显示文件和文件夹选择对话框的功能,其中:
- getSaveFileName 用于保存文件的场景,此时的对话框可以输入文件名
- getOpenFileName 用于打开文件的场景,此时的对话框可以获取到鼠标选择的文件名
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QTextEdit>
#include <QFileDialog>
#include <fstream>
#include <ostream>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 设置标题
this->setWindowTitle("简易记事本");
// 创建菜单栏
QMenuBar *menuBar = this->menuBar();
this->setMenuBar(menuBar);
// 创建菜单
// (&?):设置快捷键(?可以是任一字母)
// 菜单的快捷键需要搭配 alt 键使用
QMenu *m1 = new QMenu("文件(&F)");
// 创建菜单项
QAction *a1 = new QAction("保存(&S)");
QAction *a2 = new QAction("打开(&O)");
a1->setIcon(QIcon(":/img/save.png")); // 给菜单项设置图标
// 将菜单项加到菜单
m1->addAction(a1);
m1->addSeparator(); // 添加分割线
m1->addAction(a2);
// 将菜单加到菜单栏
menuBar->addMenu(m1);
// 使用多行输入框作为中心控件
QTextEdit *edit = new QTextEdit(this);
this->setCentralWidget(edit);
// 使用 QFileDialog 显示文件和文件夹选择对话框
QFileDialog *dialog = new QFileDialog(this);
// 设计选中保存菜单项的槽函数
connect(a1, &QAction::triggered, this, [=](){
// 弹出对话框,选择保存的路径,获取文件路径
QString fileName = dialog->getSaveFileName(this, "保存文件", "D:/");
fileName += ".txt";
// 打开文件
std::ofstream file(fileName.toStdString().c_str());
if(!file.is_open())
{
qDebug() << "文件保存失败";
return;
}
// 写入数据到文件中
const QString &text = edit->toPlainText();
file << text.toStdString();
file.close(); // 关闭文件
});
// 设计选中打开菜单项的槽函数
connect(a2, &QAction::triggered, this, [=](){
// 弹出对话框,选中打开的文件,获取文件路径
QString fileName = dialog->getOpenFileName(this, "打开文件", "D:/");
// 打开文件
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(content.c_str());
edit->setPlainText(text);
});
}
保存文件:
打开文件: