DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

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

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

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

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

首先是YourOwnApplication构造函数:

 

QString serverName = QCoreApplication::applicationName();

    QLocalSocket socket;

    socket.connectToServer(serverName);

    if (socket.waitForConnected(500)) { //如果能够连接得上的话,将参数发送到服务器,然后退出

        QTextStream stream(&socket);

        QStringList args = QCoreApplication::arguments();

        if (args.count() > 1)

            stream << args.last();

        else

            stream << QString();

        stream.flush();

        socket.waitForBytesWritten();

qApp->quit();

        return;

}

//运行到这里,说明没有实例在运行,那么创建服务器。

    m_localServer = new QLocalServer(this);

    connect(m_localServer, SIGNAL(newConnection()),

            this, SLOT(newLocalSocketConnection())); //监听新到来的连接

    if (!m_localServer->listen(serverName)) {

        if (m_localServer->serverError() == QAbstractSocket::AddressInUseError

            && QFile::exists(m_localServer->serverName())) { //确保能够监听成功

            QFile::remove(m_localServer->serverName());

            m_localServer->listen(serverName);

        }

    }

 

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

    QLocalSocket *socket = m_localServer->nextPendingConnection();

    if (!socket)

        return;

    socket->waitForReadyRead(1000);

    QTextStream stream(socket);

   … … //其他处理

    delete socket;

    mainWindow()->raise();

    mainWindow()->activateWindow(); //记得激活窗口哦

posted on   DoubleLi  阅读(1630)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2017-01-10 单片机复位电路原理介绍
2017-01-10 二极管与、或门,三极管非门电路原理
2017-01-10 Windows Route 路由表命令整理
2013-01-10 刷新--MFC界面刷新函数比较
2013-01-10 CImagelist 基本用法
2013-01-10 ORACLE 中ROWNUM用法总结!
2013-01-10 ORACLE中查询第n条到第m条的数据记录的方法
点击右上角即可分享
微信分享提示