QT实现单进程

需求:A.app之前开启了,在电脑端再打开一个A.app是不允许的。

https://www.cnblogs.com/js2854/p/qt-single-app.html

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文件:
复制代码
#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(); // 激活窗口
    }
}
复制代码

在main.cpp中使用:

复制代码
#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;
}
复制代码

 

 

 

 

posted @   野生野鸡码农  阅读(757)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
历史上的今天:
2019-06-10 设计模式中的六大基本原则
点击右上角即可分享
微信分享提示