让Qt应用程序只有一个实例

移动开发
Qt开放源代码,并且提供自由软件的用户协议。使得它可以被广泛地应用在各平台上的开放源代码软件开发中QLocalSocket 提供了一个本地的套接字

在实际应用中,我们经常需要让应用程序只有一个实例,再打开新的文档或者页面时,只是替换现在的窗口或者新打开一个标签,而不是重新启动一次应用程序。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在未来将面临新的挑战和机遇

责任编辑:zhaolei 来源: 互联网
相关推荐

2011-05-11 10:58:39

iOS

2011-01-20 07:16:48

Web程序员

2011-08-10 17:24:05

SQL语句嵌入式SQLJava

2023-05-19 08:49:58

SQLAlchemy数据库

2011-06-09 09:12:12

QT symbian

2010-08-13 13:05:30

Flex应用程序

2013-01-11 14:45:43

iOS开发移动应用iPhone

2011-03-15 19:45:27

Windows Azu

2021-07-14 17:39:46

ReactRails API前端组件

2020-10-11 20:54:39

Python开发Docker

2023-09-21 08:00:00

ChatGPT编程工具

2009-10-19 14:14:19

OSGi Web应用

2012-12-07 10:15:53

IBMdW

2022-10-21 14:21:46

JavaScript笔记技能

2013-05-13 09:31:29

Web App开发WebApp

2011-06-08 10:01:36

Windows Pho 应用程序

2011-03-10 10:45:47

Azure“Hello Worl

2011-06-08 10:24:38

Windows Pho 应用程序

2021-02-05 11:55:37

PythonWindows平台代码

2011-06-14 14:57:06

QT Python GUI
点赞
收藏

51CTO技术栈公众号