让Qt应用程序只有一个实例
创始人
2024-07-31 08:01:15
0

在实际应用中,我们经常需要让应用程序只有一个实例,再打开新的文档或者页面时,只是替换现在的窗口或者新打开一个标签,而不是重新启动一次应用程序。Qt中是否可以做到这样呢,答案是肯定的,因为Qt本身可以直接调用系统API,肯定可以做到,但是我们希望找到一个跨平台的通用的解决方案。

这就要用到Qt的QLocalSocket,QLocalServer类了,这两个类从接口上看和网络通信socket没有区别,但是它并不是真正的网络API,只是模仿了而已。这两个类在Unix/Linux系统上采用Unix域socket实现,而在Windows上则采用有名管道(named pipe)来实现。

既然是网络API,那么思路就很简单了,应用程序启动时首先会去连一个服务器(这里通过应用程序的名字来标识,就像网络端口一样),如果连接失败,那么则自己是第一个实例,就创建这么一个服务器,否则将启动参数发送到服务器,然后自动退出,而服务器会在收到通知以后进行处理。

这些动作我想最好是放在创建Application实例后,因为Qt本身有很多操作没有Application实例是无法进行操作的(至少事件循环是在创立Application以后才能启动吧),因此最好的位置就是通过继承QApplicaiton或者QCoreApplication自定义一个YourOwnApplication,然后在构造函数中进行,下面是一个示意。

首先是YourOwnApplication构造函数:

 

  1. QString serverName = QCoreApplication::applicationName();  
  2.     QLocalSocket socket;  
  3.     socket.connectToServer(serverName);  
  4.     if (socket.waitForConnected(500)) { //如果能够连接得上的话,将参数发送到服务器,然后退出  
  5.         QTextStream stream(&socket);  
  6.         QStringList args = QCoreApplication::arguments();  
  7.         if (args.count() > 1)  
  8.             stream << args.last();  
  9.         else  
  10.             stream << QString();  
  11.         stream.flush();  
  12.         socket.waitForBytesWritten();  
  13. qApp->quit();  
  14.         return;  
  15. }  
  16. //运行到这里,说明没有实例在运行,那么创建服务器。  
  17.     m_localServer = new QLocalServer(this);  
  18.     connect(m_localServer, SIGNAL(newConnection()),  
  19.             this, SLOT(newLocalSocketConnection())); //监听新到来的连接  
  20.     if (!m_localServer->listen(serverName)) {  
  21.         if (m_localServer->serverError() == QAbstractSocket::AddressInUseError  
  22.            && QFile::exists(m_localServer->serverName())) { //确保能够监听成功  
  23.             QFile::remove(m_localServer->serverName());  
  24.             m_localServer->listen(serverName);  
  25.         }  
  26.     } 

这样就保证了新启动的程序在检测到有其他实例在运行时就会自动退出,但是它发出的请求还没有被处理,下面看一下处理函数,也就是前段代码中的newLocalSocketConnection()。

  1. QLocalSocket *socket = m_localServer->nextPendingConnection();  
  2.     if (!socket)  
  3.         return;  
  4.     socket->waitForReadyRead(1000);  
  5.     QTextStream stream(socket);  
  6.    … … //其他处理  
  7.     delete socket;  
  8.     mainWindow()->raise();  
  9.     mainWindow()->activateWindow(); //记得激活窗口哦 

【编辑推荐】

 Qt Symbian SDK 安装

用Qt为Symbian开发应用程序

诺基亚发布Qt SDK 1.1正式版

详解Qt Lighthouse和Wayland

QML教程:Qt-Quick六大开源组件

Qt和KDE在未来将面临新的挑战和机遇

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...