参考:
C++ GUI Programming with Qt 4, Second Edition
本地环境:
win10专业版,64位,Qt5.12
目录
- menu和toolbars
- [context menu](#context menu)
- statusBar
- 使用对话框
- 保存设置
- 闪屏
menu和toolbars
当定义了一个action时,只要写好connect,再把action放到menu和toolbars中,就可以直接使用了,不需要反复写connect。
下面那个aboutQt()是来自QApplication的,提供的是Qt版本相关的信息。
cpp
aboutQtAction = new QAction(tr("About &Qt"), this);
aboutQtAction->setStatusTip(tr("Show the Qt library's About box"));
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
context menu
就是右键出现的菜单(也可以是快捷键)。
最简单的方法
使用 setContextMenuPolicy(Qt::ActionsContextMenu)
。这个表示讲菜单中显示的QAction作为菜单项呈现,并且可以通过添加和删除操作来动态改变菜单项。
比如在下面的代码中,spreadsheet是mainwindow的一个私有对象,继承自QTableWidget。cutAction等都是mainwindow的私有QAction,除了可以添加给mainwindow的菜单栏和工具栏,还可以加给spreadsheet,加完,设置setContextMenuPolicy,右键就有这三个action了。
cpp
void MainWindow::createContextMenu()
{
spreadsheet->addAction(cutAction);
spreadsheet->addAction(copyAction);
spreadsheet->addAction(pasteAction);
spreadsheet->setContextMenuPolicy(Qt::ActionsContextMenu);
}
自定义
重新实现QWidget::contextMenuEvent()
:创建一个QMenu
部件,加上需要的操作,然后调用exec()。
statusBar
状态栏默认是从左边开始的。
locationLabel的内容是最长的位置字符串,这样使用sizeHint()的时候就能保证其他位置的位置字符串不会超出显示范围。
setIndent()该方法接受一个整数参数,该参数是以像素为单位指定的缩进值(向右缩进)。负数的缩进值将导致内容超出部件的边界,而正数的缩进值将使内容相对于部件的边界向内缩进。
cpp
void MainWindow::createStatusBar()
{
locationLabel = new QLabel(" W999 ");
locationLabel->setAlignment(Qt::AlignHCenter);
locationLabel->setMinimumSize(locationLabel->sizeHint());
formulaLabel = new QLabel;
formulaLabel->setIndent(3);
// 添加进statusBar
statusBar()->addWidget(locationLabel);
statusBar()->addWidget(formulaLabel, 1);
// 连接
connect(spreadsheet, SIGNAL(currentCellChanged(int, int, int, int)),
this, SLOT(updateStatusBar()));
connect(spreadsheet, SIGNAL(modified()),
this, SLOT(spreadsheetModified()));
updateStatusBar();
}
使用对话框
cpp
findDialog->show();
findDialog->raise();
findDialog->activateWindow();
如果findDialog已经被唤起,也可见了,那只用show()就没办法让窗口处于最前面,还需要使用raise()和activateWindow(),因此这个等价于:
cpp
if (findDialog->isHidden()) {
findDialog->show();
} else {
findDialog->raise();
findDialog->activateWindow();
}
保存设置
软件的设置信息,我们使用MainWindow的两个函数readSettings()和writeSettings()帮助读取和保存:
-
QSettings使用公司名称和应用名称作为标识符存储设置信息,存储位置和形式因os而异;
-
QSettings使用键值对的形式存储设置信息,key有点像文件路径,是可以有subkey的,可以使用诸如
findDialog/matchCase
这样的内容,也可以用beginGroup
和endGroup
包裹:cppsettings.beginGroup("findDialog"); settings.setValue("matchCase", caseCheckBox->isChecked()); ... // 其他内容,如findDialog/searchBack settings.endGroup();
-
QSettings的value可以是各种变量,只要是QVariant支持的,也包括已注册的、自定义类型
-
QSettings对象可以在软件运行的任何时候、在代码的任何位置,进行查询和修改
-
在MainWindow的构造函数里,调用readSettings()读取设置信息;
-
在closeEvent()里,调用writeSettings()保存设置信息;
readSettings()
cpp
void MainWindow::readSettings(){
QSettings settings("公司名称", "app名称");
// 恢复上一次的布局
restoreGeometry(settings.value("geometry").toByteArray());
// 自定义的设置...
recentFiles = settings.value("recentFiles").toStringList();
updateRecentFileActions();
}
说明:
- 第一次运行的时候,因为没有设置,所以窗口大小和位置是随机且合理的,最近使用的文件列表也是空的
writeSettings()
cpp
void MainWindow::writeSettings(){
QSettings settings("公司名称", "app名称");
// 保存窗口的geometry信息(position,size)
settings.setValue("geometry", saveGeometry());
// 其他需要保存的信息
// 比如最近打开的文件(list)
settings.setValue("recentFiles", recentFiles);
}
闪屏
闪屏(splash screens)指的是软件启动时闪过的画面。设计这个的目的可能是传递信息(比如公司名称和软件名称、宣传logo等),也可能是为了掩盖软件初始化的耗时。闪屏也可以用在软件内耗时比较长的操作里(比如给一个加载进度条,让用户安心等待)。
用在软件启动时
一般写在main函数里:
cpp
// main.cpp
#include <QApplication>
#include <QSplashScreen>
#include <QTimer>
#include <QEventLoop>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 闪屏,欢迎
QSplashScreen *splash = new QSplashScreen;
// 添加一个图片
splash->setPixmap(QPixmap("://resources/img/welcome_img.jpg"));
splash->show();
// 可以添加额外的文字.此处是将文字放在图片的左下角位置
Qt::Alignment bottomLeft = Qt::AlignLeft | Qt::AlignBottom;
// 文字可以使用html修改格式
splash->showMessage(QObject::tr("<h2>PDAA 3.0</h2>"), bottomLeft, Qt::black);
// 模拟软件加载耗时
QTimer timer;
QEventLoop loop;
QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
timer.start(5000); // 等待5秒
loop.exec();
// 实际的窗口加载过程
MainWindow w;
w.show();
splash->finish(&w);
delete splash;
return a.exec();
}