Qt单一应用实例判断

原本项目中使用QSharedMemory的方法来判断当前是否已存在运行的实例,但在MacOS上,当程序异常崩溃后,QSharedMemory没有被正常销毁,导致应用程序无法再次被打开。

对此,Qt assistant中有相关说明:

摘抄 qt-solutions/qtsingleapplication at master · qtproject/qt-solutions (github.com) 实现了一个single application的类,记录下来:

main.cpp

cpp 复制代码
#include "mainwindow.h"
#include "singleapplication.h"

int main(int argc, char *argv[])
{
    CSingleApplication a(argc, argv);
    if (a.isRunning()) {
        return 0;
    }

    MainWindow w;
    w.show();
    a.setActivationWindow(&w);

    return a.exec();
}

singleapplication.cpp

cpp 复制代码
#include "singleapplication.h"
#include <QFileInfo>
#include <QLocalSocket>
#include <QLocalServer>
#include <QWidget>

CSingleApplication::CSingleApplication(int& argc, char** argv)
    : QApplication(argc, argv)
{
    m_strServerName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
    initLocalConn();
}

CSingleApplication::~CSingleApplication()
{

}

bool CSingleApplication::isRunning()
{
    return m_isRunning;
}

void CSingleApplication::setActivationWindow(QWidget* w)
{
    m_pActivateWin = w;
}

void CSingleApplication::initLocalConn()
{
    m_isRunning = false;

    QLocalSocket socket;
    socket.connectToServer(m_strServerName);
    if (socket.waitForConnected(200)) {
        m_isRunning = true;
        return;
    }

    createLocalServer();
}

void CSingleApplication::createLocalServer()
{
    m_pLocalServer = new QLocalServer(this);
    connect(m_pLocalServer, &QLocalServer::newConnection, this, &CSingleApplication::onNewConnection);
    if (!m_pLocalServer->listen(m_strServerName)) {
        if (QAbstractSocket::AddressInUseError == m_pLocalServer->serverError()) {
            QLocalServer::removeServer(m_strServerName);
            m_pLocalServer->listen(m_strServerName);
        }
    }
}

void CSingleApplication::activateWindow()
{
    if (nullptr != m_pActivateWin) {
        m_pActivateWin->show();
        m_pActivateWin->raise();
        m_pActivateWin->activateWindow();
    }
}

void CSingleApplication::onNewConnection()
{
    if (nullptr == m_pLocalServer) {
        return;
    }

    QLocalSocket* socket = m_pLocalServer->nextPendingConnection();
    if (nullptr != socket) {
        socket->waitForReadyRead(300);
        delete socket;
        activateWindow();
    }
}

singleapplication.h

cpp 复制代码
#ifndef CSINGLEAPPLICATION_H
#define CSINGLEAPPLICATION_H

#include <QApplication>

class QLocalServer;

class CSingleApplication : public QApplication
{
public:
    CSingleApplication(int& argc, char** argv);
    virtual ~CSingleApplication() override;

public:
    bool isRunning();
    void setActivationWindow(QWidget* w);

private:
    bool          m_isRunning = false;
    QWidget*      m_pActivateWin = nullptr;
    QString       m_strServerName;
    QLocalServer* m_pLocalServer = nullptr;

    void initLocalConn();
    void createLocalServer();
    void activateWindow();

private slots:
    void onNewConnection();
};

#endif // CSINGLEAPPLICATION_H
相关推荐
程序员如山石5 小时前
QTabWidget动态生成标签页
c++·qt
H2122021656 小时前
P7 QT项目----会学天气预报
开发语言·qt
T1an-116 小时前
Qt面试常问
开发语言·qt
Wyn_18 小时前
【QT】自定义QWidget设置圆角+边框(重绘paintEvent)
qt·qwidget
漫步企鹅18 小时前
【PDF】Qt生成PDF文件,占用存储小
c++·qt·pdf
牵牛老人19 小时前
聊聊Qt 中的多面手之QVariant 变体类
开发语言·数据库·qt
浪小满1 天前
怎样解决在ubuntu 22.04上QT: DataVisualization控件显示黑屏的问题
linux·qt·ubuntu
yxc_inspire1 天前
基于Qt的app开发第十五天
c++·qt·面向对象·qtreeview
做一个坚强的女汉子1 天前
Qt Quick 与 QML(二)qml中的顶级窗口
qt·qml
追风赶月、1 天前
【QT】控件二(输入类控件、多元素控件、容器类控件与布局管理器)
开发语言·qt