Qt-QtSingleApplication详解

概述

QtSingleApplication源自Qt-Solutions,长期维护。

用于创建单实例应用程序。

代码解析

构造函数

1
2
3
4
5
6
7
8
9
10
11
12
public:
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
QtSingleApplication(const QString &id, int &argc, char **argv);
// Qt 4
#if QT_VERSION < 0x050000
QtSingleApplication(int &argc, char **argv, Type type);
// Linux操作系统
# if defined(Q_WS_X11)
QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
# endif // Q_WS_X11

各类构造函数都是对QApplication的重写,调用了sysInit函数。

sysInit函数

上文说到,QtSingleApplication的构造函数都是对QApplication的重写。

1
2
3
4
5
6
void QtSingleApplication::sysInit(const QString &appId)
{
actWin = 0;
peer = new QtLocalPeer(this, appId);
connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
}

QtLocalPeer

其中关键对象为QtLocalPeer,其提供的主要函数如下

1
2
3
4
5
6
7
8
9
public:
// 通过传入的appId,创建QLockedFile锁定文件以及QLocalServer服务器
QtLocalPeer(QObject *parent = 0, const QString &appId = QString());
// 尝试通过WriteLock方式锁定文件为失败时,返回true,其余为false
bool isClient();
// 通过QLocalSocket发送消息
bool sendMessage(const QString &message, int timeout);
// 返回appID
QString applicationId() const;

QtSingleApplication其他关键函数

是否有实例运行中

1
2
3
4
bool QtSingleApplication::isRunning()
{
return peer->isClient();
}

通过内部QtLocalPeer对象的isClient函数判断是否运行有实例。

消息的传递

1
2
3
4
5
public Q_SLOTS:
bool QtSingleApplication::sendMessage(const QString &message, int timeout = 5000)
{
return peer->sendMessage(message, timeout);
}

通过内部QtLocalPeer对象的sendMessage函数,向服务器发送消息:当有多个实例时,如果当前实例为服务器,则直接返回,如果为客户端,则通过QLocalSocket连接到当前应用程序唯一ID的QLocalServer,以传递消息。

案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <qtsingleapplication.h>

int main(int argc, char *argv[])
{
QtSingleApplication app(QString("appId"),argc,argv);
if (app.isRunning())
{
app.sendMessage("raise_window_noop");
return EXIT_SUCCESS;
}
MainWindow m;
app.setActivationWindow(&m);
m.show();
return app.exec();
}

当调用了setActivationWindow后,单例应用程序收到消息时,会调用activateWindow函数,激活窗口。

当然如果不希望激活窗口,可以使用setActivationWindow(&windowName,false)取消设置,并自行书写槽函数MainWindow::messageHandle(const QString& msg)后,使用connect(&app,&QtSingleApplication::messageReceived,&w,&MainWindow::messageHandle)连接。