Qt单实例运行

在用Qt写程序时候可能遇到避免程序重复启动的问题,我们知道用MFC时有个FindWindow函数可以进行窗口查找于是想Qt能否实现呢,经过一番摸索和折腾终于搞定(测试环境为Win7和Ubuntu)

系列目录

本文是系列教程<跟随Designer源码学Qt>中的一篇详见跟随Designer源码学Qt

参考


具体见链接Qt学习一二三

根据大神的说明大致有三种:

  • QSharedMemory
  • QLocalServer
  • QtSingleApplication
    本文着重介绍QLocalServer,在大神的代码基础上修改了下使程序启动时判断如果已经启动则进行窗口显示

代码

废话不多说直接上硬货

头文件

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
32
33
#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H

#include <QApplication>
#include <QWidget>

class QLocalServer;
class QWidget;

class SingleApplication : public QApplication
{
    Q_OBJECT

public:
    SingleApplication(int &argc, char **argv);
    ~SingleApplication();

public:
    bool isRunning();

    //保存主窗口指针
    void setSingleMainWindow(QWidget* w);

private slots:
    void newLocalConnection();

private:
    bool m_bRunning;
    QLocalServer *m_pServer;
    QWidget *m_widget;
};

#endif // SINGLEAPPLICATION_H

 

cpp文件

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "singleapplication.h"
#include <QLocalSocket>
#include <QLocalServer>
#include <QFile>
#include <QTextStream>
#include <QWidget>
#include <QDebug>

static const char *ApplicationName = "myApp";

SingleApplication::SingleApplication(int &argc, char **argv):
    QApplication(argc, argv),
    m_mousePoint(0, 0),
    m_mousePressed(false),
    m_bRunning(false),
    m_pServer(Q_NULLPTR),
    m_widget(Q_NULLPTR)
{
    setOrganizationName(QStringLiteral("MyProject"));
    setApplicationName(QLatin1String(ApplicationName));

#if !defined(Q_OS_OSX)
    setWindowIcon(QIcon(QStringLiteral(":/image/calcapp.png")));
#endif

    QString strServerName = QString("%1%2")
            .arg(QCoreApplication::organizationName())
            .arg(QCoreApplication::applicationName());

    QLocalSocket socket;
    socket.connectToServer(strServerName);

    if (socket.waitForConnected(500)){
        QTextStream stream(&socket);
        QStringList args = QCoreApplication::arguments();
        QString strArg = (args.count() > 1) ? args.last() : "";
        stream << strArg;
        stream.flush();

        qDebug() << "Have already connected to server.";
        socket.waitForBytesWritten();
        m_bRunning = true;
    }
    else{
        // 如果不能连接到服务器,则创建
        m_pServer = new QLocalServer(this);

        connect(m_pServer, SIGNAL(newConnection()), this, SLOT(newLocalConnection()));

        if (m_pServer->listen(strServerName)){
            // 防止程序崩溃,残留进程服务,直接移除
            if ((m_pServer->serverError() == QAbstractSocket::AddressInUseError)
                    && QFile::exists(m_pServer->serverName())){
                QFile::remove(m_pServer->serverName());
                m_pServer->listen(strServerName);
            }
        }
    }

}

SingleApplication::~SingleApplication()
{

}

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


void SingleApplication::setSingleMainWindow(QWidget *w)
{
    m_widget = w;
}


void SingleApplication::newLocalConnection()
{
    QLocalSocket *pSocket = m_pServer->nextPendingConnection();
    if (pSocket != Q_NULLPTR){
        pSocket->waitForReadyRead(1000);

        QTextStream in(pSocket);
        QString strValue;
        in >> strValue;
        delete pSocket;
        pSocket = Q_NULLPTR;

        //如果窗口不为空,则前端显示
        //核心代码
        if(m_widget){
            m_widget->showMaximized();
            m_widget->activateWindow();
            m_widget->raise();
        }
    }
}

 

用法

别忘了在pro文件中加上网络依赖
QT += network

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "singleapplication.h"
#include <QDialog>

int main(int argc, char *argv[])
{
    SingleApplication a(argc, argv);

    if (a.isRunning()){
        return 0;
    }

    QDialog w;
    w.show();

    //保存指针用于显示
    a.setSingleMainWindow(&w);
    return a.exec();
}

遇到的坑

在Win7上可以随心所欲的运行,不料放到Ubuntu上之后崩的噼里啪啦,经过一番折腾终于找到个大坑

  1. 连接服务器的代码要放到构造函数中
  2. setApplicationName(QLatin1String(ApplicationName));中的参数要提前定义为static const char *

PS

在使用刘典武大神的代码时AppInit 也要放到SingleApplication的构造函数中,顺便说一句 QTimer::singleShot真香

PPS

你没有看错,我确实把大神的CSDN博客给撸下来,做成了高清无码的PDF….
嗯,爬虫在手,天下我有…..

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值