查看完整版本: [-- Qt单实例运行 --]

QTCN开发网 -> Qt代码秀 -> Qt单实例运行 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

spygg 2019-06-25 23:46

Qt单实例运行

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


详情见我的博客



代码主要是Qt学习一二三中的一篇,膜拜之.......

  1. #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
  1. #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();
            }
        }
    }


使用
  1. #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();
    }





20091001753 2019-06-26 21:14
在 win 系统下,2行就解决了。

  1. auto mutex = CreateMutex(nullptr, FALSE,(LPCWSTR)qApp->applicationFilePath().utf16());
    if(mutex&&GetLastError()==ERROR_ALREADY_EXISTS)exit(0);



笑颜 2019-06-26 23:03
qt creator源码里面有封装一个QtSingleApplication类,直接用就行了。

spygg 2019-06-27 07:30
笑颜:qt creator源码里面有封装一个QtSingleApplication类,直接用就行了。 (2019-06-26 23:03) 

嗯,知道这个方案,好像代码很多的样子

spygg 2019-06-27 07:32
20091001753:在 win 系统下,2行就解决了。
auto mutex = CreateMutex(nullptr, FALSE,(LPCWSTR)qApp->applicationFilePath().utf16());
if(mutex&&GetLastError()==ERROR_ALREADY_EXISTS)exit(0);
....... (2019-06-26 21:14) 

你说的这个我在MFC中一直这么用的,但是重复启动的时候就直接退出了,没有我的把已有程序激活的效果

kaon 2019-06-30 16:57
https://stackoverflow.com/questions/5006547/qt-best-practice-for-a-single-instance-app-protection
这里也可以参考下

spygg 2019-07-02 22:32
kaon:https://stackoverflow.com/questions/5006547/qt-best-practice-for-a-single-instance-app-protection
这里也可以参考下 (2019-06-30 16:57) 

恩恩,我就是参考了这个,创新点为在main.cpp中保存主窗口指针用于激活前端显示

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

gfanny 2019-09-20 12:49
赞,给好评!激动窗口是正道。楼主收集的内容很多啊?有没有计划PDF文档分享一下


查看完整版本: [-- Qt单实例运行 --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Gzip disabled