免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4062 | 回复: 0
打印 上一主题 下一主题

让Qt应用程序只运行一个实例 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-02-18 01:26 |只看该作者 |倒序浏览
在实际应用中,我们经常需要让应用程序只有一个实例,再打开新的文档或者页面时,只是替换现在的窗口或者新打开一个标签,而不是重新启动一次应用程序。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. }
  27. // 这样就保证了新启动的程序在检测到有其他实例在运行时就会自动退出,
  28. // 但是它发出的请求还没有被处理,
  29. // 下面看一下处理函数,也就是前段代码中的newLocalSocketConnection()。

  30. QLocalSocket *socket = m_localServer->nextPendingConnection();

  31. if (!socket)
  32.         return;

  33. socket->waitForReadyRead(1000);
  34. QTextStream stream(socket);
  35. //其他处理

  36. delete socket;
  37. mainWindow()->raise();
  38. mainWindow()->activateWindow(); //记得激活窗口哦
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP