Qt 实现应用程序单实例

这篇具有很好参考价值的文章主要介绍了Qt 实现应用程序单实例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实现方案

目前使 Qt 运行一个实例有如下几种方式:
1.QSharedMemory
使用共享内存,当第二个进程启动时,判断内存区数据是否建立,如有,则退出;这种方式有弊端,在程序发生崩溃时,未及时清除共享区数据,导致程序不能正常启动。
2.文件锁
在程序运行的时候就在目录下创建一个文件,当程序运行时就判断这个文件是否存在,如果存在说明程序已经在运行。其本质与 QSharedMemory 相同。
3.利用QLocalServer
使Qt应用程序能够单实例运行的典型实现方法是使用共享内存实现。该方法实现简单,代码简洁。
但有一个致命缺陷:共享内存(QSharedMemory)实现的单程序运行,当运行环境是UNIX时,并且程序不幸崩溃,会导致共享内存无法释放,从而无法重新运行程序!
4.QtSingleApplication
使用 Qt 扩展库 QtSingleApplication,能很好的解决这个问题。
QSingleApplication 是 Qt 提供的一个 solution ,它不包含在 Qt 的 library 中。遵循 LGPL 协议。Qt 欢迎里面有例子。

二、实现代码

下面给出了 LocalServer 方式的实现代码。

SingleApplication.h:

#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H

#include <QObject>
#include <QApplication>
#include <QtNetwork/QLocalServer>
#include <QWidget>

class SingleApplication : public QApplication {
        Q_OBJECT
    public:
        SingleApplication(int &argc, char **argv);

        bool isRunning();                // 是否已經有实例在运行
        QWidget *w;                        // MainWindow指针

    private slots:
        // 有新连接时触发
        void _newLocalConnection();

    private:
        // 初始化本地连接
        void _initLocalConnection();
        // 创建服务端
        void _newLocalServer();
        // 激活窗口
        void _activateWindow();

        bool _isRunning;                // 是否已經有实例在运行
        QLocalServer *_localServer;     // 本地socket Server
        QString _serverName;            // 服务名称
};

#endif // SINGLEAPPLICATION_H

SingleApplication.cpp:文章来源地址https://www.toymoban.com/news/detail-497979.html

#include "SingleApplication.h"
#include <QtNetwork/QLocalSocket>
#include <QFileInfo>

#define TIME_OUT                (500)    // 500ms

SingleApplication::SingleApplication(int &argc, char **argv)
    : QApplication(argc, argv)
    , w(NULL)
    , _isRunning(false)
    , _localServer(NULL) {

    // 取应用程序名作为LocalServer的名字
    _serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();

    _initLocalConnection();
}



// 说明:
// 检查是否已經有一个实例在运行, true - 有实例运行, false - 没有实例运行

bool SingleApplication::isRunning() {
    return _isRunning;
}


// 说明:
// 通过socket通讯实现程序单实例运行,监听到新的连接时触发该函数

void SingleApplication::_newLocalConnection() {
    QLocalSocket *socket = _localServer->nextPendingConnection();
    if(socket) {
        socket->waitForReadyRead(2*TIME_OUT);
        delete socket;

        // 其他处理,如:读取启动参数

        _activateWindow();
    }
}


// 说明:
// 通过socket通讯实现程序单实例运行,
// 初始化本地连接,如果连接不上server,则创建,否则退出

void SingleApplication::_initLocalConnection() {
    _isRunning = false;

    QLocalSocket socket;
    socket.connectToServer(_serverName);
    if(socket.waitForConnected(TIME_OUT)) {
        fprintf(stderr, "%s already running.\n",
                _serverName.toLocal8Bit().constData());
        _isRunning = true;
        // 其他处理,如:将启动参数发送到服务端
        return;
    }

    //连接不上服务器,就创建一个
    _newLocalServer();
}


// 说明:
// 创建LocalServer

void SingleApplication::_newLocalServer() {
    _localServer = new QLocalServer(this);
    connect(_localServer, SIGNAL(newConnection()), this, SLOT(_newLocalConnection()));
    if(!_localServer->listen(_serverName)) {
        // 此时监听失败,可能是程序崩溃时,残留进程服务导致的,移除之
        if(_localServer->serverError() == QAbstractSocket::AddressInUseError) {
            QLocalServer::removeServer(_serverName); // <-- 重点
            _localServer->listen(_serverName); // 再次监听
        }
    }
}


// 说明:
// 激活主窗口

void SingleApplication::_activateWindow() {
    if(w) {
        w->show();
        w->raise();
        w->activateWindow(); // 激活窗口
    }
}

调用示例:

#include "MainWindow.h"
#include "SingleApplication.h"

int main(int argc, char *argv[]) {
    SingleApplication a(argc, argv);
    if(!a.isRunning()) {
        MainWindow w;
        a.w = &w;

        w.show();

        return a.exec();
    }
    return 0;
}

到了这里,关于Qt 实现应用程序单实例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Qt、PYTHON智能校园防御系统应用程序,实现了摄像头数据采集、人脸识别、口罩识别、 数据统计等功能

    完整项目地址:https://download.csdn.net/download/lijunhcn/88453470 项目结构 环境选型 语言:Python 操作系统:Windows 数据库:MySQL 窗口界面:PyQT API接口:百度AI接口,用以实现人脸登陆与注册 远程MySQL表结构 远程表结构sql脚本 项目背景 智能校园防御软件是实现了一款基于摄像头数据

    2024年02月03日
    浏览(44)
  • 毕设项目——基于Qt、PYTHON智能校园防御系统应用程序,实现了摄像头数据采集、人脸识别、口罩识别、 数据统计等功能

    完整项目地址:https://download.csdn.net/download/lijunhcn/88453470 项目结构 环境选型 语言:Python 操作系统:Windows 数据库:MySQL 窗口界面:PyQT API接口:百度AI接口,用以实现人脸登陆与注册 远程MySQL表结构 远程表结构sql脚本 项目背景 智能校园防御软件是实现了一款基于摄像头数据

    2024年02月04日
    浏览(35)
  • 【QT】MDI应用程序设计

    目录 1 MDI简介 2 文档窗口类QFormDoc的设计 3 MDI主窗口设计与子窗口的使用 3.1 主窗口界面设计 3.2 MDI子窗口的创建与加入 3.3 QMdiArea常用功能函数 3.4 MDI的信号         传统的应用程序设计中有多文档界面(Multi-documentInterface,MDI)应用程序,Qt为设计 MDI应用程序提供了支持。

    2024年01月25日
    浏览(31)
  • 【QT】多窗体应用程序设计

    目录 1主要的窗体类及其用途 2 窗体类重要特性的设置 2.1 setAttribute()函数 2.2 setWindowFlags()函数 2.3 setWindowState()函数 2.4 setWindowModality()函数 2.5 setWindowOpacity()函数 3 多窗口应用程序的设计 3.1 主窗口设计 3.2 QFormDoc类的设计 3.3 QFormDoc类的使用 3.4 QFormTable类的设计 3.5 QFormTable类的使

    2024年01月18日
    浏览(36)
  • 《Qt开发》MDI应用程序

    实现多个子窗体的自定义布局(自定义子窗体尺寸和位置)、平铺布局(titleSubWindows)和分页模式(QMdi::TabbedView)。 运行效果图 初始布局(自定义布局) 平铺布局 多页模式 实现过程 1. 创建项目MdiFirstDemo,并创建3个子窗体,分别为FirstSubWindow、SecondSubWindow和ThirdSubWindow。

    2024年01月16日
    浏览(35)
  • <QT开发> QT开发工具-之-QT应用程序打包

    <QT开发> QT开发工具-之-QT应用程序打包 笔者为什么会写这篇文章呢?这是因为,笔者使用windows QT开发了一个测试工具。目的是通过TCP/IP测试其它应用程序。首先这个QT程序是笔者自己开发的,所以笔者的电脑当然是可以运行这个QT程序的,但是想要这个QT程序在其它同事的

    2024年02月12日
    浏览(40)
  • Qt应用程序中的 QApplication

    QApplication类是一个Qt框架中核心的应用程序类,它提供了管理应用程序的框架、事件循环和系统级配置的基础。在本文中,我们将详细介绍QApplication类的功能和应用场景。 通常,我们在主函数中创建 QApplication 对象。在创建时,我们可以指定一些命令行选项和特定于平台的参

    2024年02月15日
    浏览(30)
  • Qt Linux 环境中应用程序打包

    系统环境:Ubuntu20.04LTS 开发环境:Qt5.14.1 在进入程序部署打包之前,阅读官方的部署文档Deploy,通常情况下,我们在开发的时候,Qt Creator 的左下角构建模式为Debug,便于我们调试编写程序。Qt的三个构建模式Debug、Profile、Release的区别是: debug可以调试程序,而release不可以。在

    2024年02月01日
    浏览(27)
  • qt随记:拖动文件方式打开应用程序

    结果 即从main入口进入

    2024年02月10日
    浏览(42)
  • 基于Qt HTTP应用程序项目案例

    main函数创建对象空间,确认窗口的大小和坐标。

    2024年02月07日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包