功能介绍
QSingleApplication是一个用于确保应用程序单实例运行的类,这在防止多个应用实例运行时非常有用。该类基于 Qt 框架进行开发,并继承自QApplication,使其可以完全替代常规的 Qt 应用程序类使用。
- 初始化加载样式表文件
- 初始化加载第三方字体库
- 进程间通信
进程间通信的意义
既然该类是用来确保单实例运行的,那么就不涉及到多进程,为什么要实现进程间通信功能呢?
在实现一个文本编辑器程序时,用户往往通过双击文本文件来打开对应的编辑器程序,如果当前已经打开了编辑器程序,用户再通过双击其他文本文件时,需要将新打开的文本文件展示在已经打开的程序中,而不是重新启动一个程序来展示。
每次用户双击文本文件时都是启动编辑器程序,在程序内部将本次要打开的文本文件路径通过进程间通信的方式传递给已经打开了的程序(第一次打开的程序),然后再进行文件处理。
所以,在某些特殊的应用场景下,进程间通信还是非常有必要的。
实现
C++
QSingleApplication::QSingleApplication(int &argc, char **argv, const QString &uniqueKey)
: QApplication(argc, argv)
, m_uniqueKey(uniqueKey)
, m_isRunning(false)
{
m_sharedMemory.setKey(uniqueKey);
// 尝试创建共享内存段,如果失败则表示已有实例在运行
if (m_sharedMemory.create(1)) {
// 没有其他实例在运行
m_localServer = new QLocalServer(this);
connect(m_localServer,
&QLocalServer::newConnection,
this,
&QSingleApplication::handleNewConnection);
QString serverName = uniqueKey;
QFile::remove(serverName); // 删除之前的残留文件
if (!m_localServer->listen(serverName)) {
qWarning() << "Unable to start the local server:" << m_localServer->errorString();
}
} else {
// 另一个实例正在运行
m_isRunning = true;
}
}
C++
int main(int argc, char *argv[])
{
QSingleApplication app(argc, argv, "test");
if (app.isAnotherInstanceRunning()) {
app.sendMessage("Another instance tried to start.");
return 0;
}
app.initializeStyleSheet(":/res/black.css");
app.initializeFonts("./font");
MainWindow w;
w.show();
QObject::connect(&app, &QSingleApplication::messageReceived, [](const QString &message) {
qDebug() << "Received message:" << message;
});
return app.exec();
}