• 3787阅读
  • 7回复

Qt单实例运行 [复制链接]

上一主题 下一主题
离线spygg
 

只看楼主 倒序阅读 楼主  发表于: 2019-06-25
— 本帖被 圣域天子 从 Qt 作品展 移动到本区(2019-09-20) —
在用Qt写程序时候可能遇到避免程序重复启动(再次启动时直接把已有界面的拉倒前台),我们知道用MFC时有个FindWindow函数可以进行窗口查找于是想Qt能否实现呢,经过一番摸索和折腾终于搞定(测试环境为Win7和Ubuntu)


详情见我的博客



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

  1. #ifndef SINGLEAPPLICATION_H
  2. #define SINGLEAPPLICATION_H
  3. #include <QApplication>
  4. #include <QWidget>
  5. class QLocalServer;
  6. class QWidget;
  7. class SingleApplication : public QApplication
  8. {
  9.     Q_OBJECT
  10. public:
  11.     SingleApplication(int &argc, char **argv);
  12.     ~SingleApplication();
  13. public:
  14.     bool isRunning();
  15.     //保存主窗口指针
  16.     void setSingleMainWindow(QWidget* w);
  17. private slots:
  18.     void newLocalConnection();
  19. private:
  20.     bool m_bRunning;
  21.     QLocalServer *m_pServer;
  22.     QWidget *m_widget;
  23. };
  24. #endif // SINGLEAPPLICATION_H
  1. #include "singleapplication.h"
  2. #include <QLocalSocket>
  3. #include <QLocalServer>
  4. #include <QFile>
  5. #include <QTextStream>
  6. #include <QWidget>
  7. #include <QDebug>
  8. static const char *ApplicationName = "myApp";
  9. SingleApplication::SingleApplication(int &argc, char **argv):
  10.     QApplication(argc, argv),
  11.     m_mousePoint(0, 0),
  12.     m_mousePressed(false),
  13.     m_bRunning(false),
  14.     m_pServer(Q_NULLPTR),
  15.     m_widget(Q_NULLPTR)
  16. {
  17.     setOrganizationName(QStringLiteral("MyProject"));
  18.     setApplicationName(QLatin1String(ApplicationName));
  19. #if !defined(Q_OS_OSX)
  20.     setWindowIcon(QIcon(QStringLiteral(":/image/calcapp.png")));
  21. #endif
  22.     QString strServerName = QString("%1%2")
  23.             .arg(QCoreApplication::organizationName())
  24.             .arg(QCoreApplication::applicationName());
  25.     QLocalSocket socket;
  26.     socket.connectToServer(strServerName);
  27.     if (socket.waitForConnected(500)){
  28.         QTextStream stream(&socket);
  29.         QStringList args = QCoreApplication::arguments();
  30.         QString strArg = (args.count() > 1) ? args.last() : "";
  31.         stream << strArg;
  32.         stream.flush();
  33.         qDebug() << "Have already connected to server.";
  34.         socket.waitForBytesWritten();
  35.         m_bRunning = true;
  36.     }
  37.     else{
  38.         // 如果不能连接到服务器,则创建
  39.         m_pServer = new QLocalServer(this);
  40.         connect(m_pServer, SIGNAL(newConnection()), this, SLOT(newLocalConnection()));
  41.         if (m_pServer->listen(strServerName)){
  42.             // 防止程序崩溃,残留进程服务,直接移除
  43.             if ((m_pServer->serverError() == QAbstractSocket::AddressInUseError)
  44.                     && QFile::exists(m_pServer->serverName())){
  45.                 QFile::remove(m_pServer->serverName());
  46.                 m_pServer->listen(strServerName);
  47.             }
  48.         }
  49.     }
  50. }
  51. SingleApplication::~SingleApplication()
  52. {
  53. }
  54. bool SingleApplication::isRunning()
  55. {
  56.     return m_bRunning;
  57. }
  58. void SingleApplication::setSingleMainWindow(QWidget *w)
  59. {
  60.     m_widget = w;
  61. }
  62. void SingleApplication::newLocalConnection()
  63. {
  64.     QLocalSocket *pSocket = m_pServer->nextPendingConnection();
  65.     if (pSocket != Q_NULLPTR){
  66.         pSocket->waitForReadyRead(1000);
  67.         QTextStream in(pSocket);
  68.         QString strValue;
  69.         in >> strValue;
  70.         delete pSocket;
  71.         pSocket = Q_NULLPTR;
  72.         //如果窗口不为空,则前端显示
  73.         //核心代码
  74.         if(m_widget){
  75.             m_widget->showMaximized();
  76.             m_widget->activateWindow();
  77.             m_widget->raise();
  78.         }
  79.     }
  80. }


使用
  1. #include "singleapplication.h"
  2. #include <QDialog>
  3. int main(int argc, char *argv[])
  4. {
  5.     SingleApplication a(argc, argv);
  6.     if (a.isRunning()){
  7.         return 0;
  8.     }
  9.     QDialog w;
  10.     w.show();
  11.     //保存指针用于显示
  12.     a.setSingleMainWindow(&w);
  13.     return a.exec();
  14. }




签名就是这么浪
离线20091001753

只看该作者 1楼 发表于: 2019-06-26
在 win 系统下,2行就解决了。

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


(づ ̄ 3 ̄)づ
离线笑颜

只看该作者 2楼 发表于: 2019-06-26
qt creator源码里面有封装一个QtSingleApplication类,直接用就行了。
离线spygg

只看该作者 3楼 发表于: 2019-06-27
回 笑颜 的帖子
笑颜:qt creator源码里面有封装一个QtSingleApplication类,直接用就行了。 (2019-06-26 23:03) 

嗯,知道这个方案,好像代码很多的样子
签名就是这么浪
离线spygg

只看该作者 4楼 发表于: 2019-06-27
回 20091001753 的帖子
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

只看该作者 5楼 发表于: 2019-06-30
离线spygg

只看该作者 6楼 发表于: 2019-07-02
回 kaon 的帖子
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

只看该作者 7楼 发表于: 2019-09-20
赞,给好评!激动窗口是正道。楼主收集的内容很多啊?有没有计划PDF文档分享一下
快速回复
限100 字节
 
上一个 下一个