使Qt程序只能运行一个实例的3种方法

版权:http://blog.csdn.net/robertkun


1. 共享内存的方法

Unix: QSharedMemory "owns" the shared memory segment. When the last thread or process that has an instance of QSharedMemory attached to a particular shared memory segment detaches from the segment by destroying its instance of QSharedMemory, the Unix kernel release the shared memory segment. But if that last thread or process crashes without running the QSharedMemory destructor, the shared memory segment survives the crash.

(据说这种方法在Linux系统下会有一个内存释放的问题,在某种情况下会引起程序的异常或崩溃)

[cpp]  view plain  copy
  1.    
  2. // 确保只运行一次   
  3.   
  4. QSystemSemaphore sema("JAMKey",1,QSystemSemaphore::Open);   
  5. sema.acquire();// 在临界区操作共享内存   SharedMemory   
  6.   
  7. QSharedMemory mem("SystemObject");// 全局对象名   
  8. if (!mem.create(1))// 如果全局对象以存在则退出   
  9. {   
  10.     QMessageBox::information(0, MESSAGEBOXTXT,"An instance has already been running.");  
  11.    
  12.     sema.release();// 如果是 Unix 系统,会自动释放。   
  13.   
  14.     return 0;   
  15. }   
  16.   
  17. sema.release();// 临界区   


2. 使用QLocalServer和QLocalSocket类

下面是自已的写的代码,主要是在运行第二实例的时候,有一个提示的作用:

1. 切换到当前程序,并将当前程序最大化显示到前面。

2.关闭当前程序的进程,打开新程序。

(注意:需要在你的.pro里加上QT += network)

头文件:

[cpp]  view plain  copy
  1. #ifndef PSA_USR_LOGIN_H  
  2. #define PSA_USR_LOGIN_H  
  3.   
  4. #include   
  5. #include   
  6. #include   
  7.   
  8. #include "ui_DlgUsrLogin.h"  
  9.   
  10. #define PROCESS_SHOW        1  
  11. #define PROCESS_RESTART     2  
  12. #define PROCESS_STOP        3  
  13.   
  14. const QString PRO_SHOW      = "PRO_SHOW";  
  15. const QString PRO_RESTART   = "PRO_RESTART";  
  16. const QString PRO_STOP      = "PRO_STOP";  
  17.   
  18. class CUsrLogin : public QDialog  
  19. {  
  20.     Q_OBJECT  
  21.   
  22. public:  
  23.     CUsrLogin(const QString& serverName, QWidget* parent = NULL);  
  24.     virtual ~CUsrLogin();  
  25.   
  26.     int GetIndex() const;  
  27.     bool InitServer();  
  28.   
  29. signals:  
  30.     void sig_newOrder(const QString&);  
  31.   
  32. private slots:  
  33.     void slot_ok();  
  34.     void slot_cancel();  
  35.     void slot_btnGroupClicked(int);  
  36.     void slot_newConnection();  
  37.     void slot_readyRead();  
  38.     void slot_timeFinished();  
  39.   
  40. private:  
  41.     int IsServerRun(const QString & servername);  
  42.   
  43. private:  
  44.     Ui::DlgUsrLogin ui;  
  45.   
  46.     int mIndex;  
  47.     QString mServerName;  
  48.     QLocalServer* mpServer;  
  49.     QTimeLine *mpTimeLine;  
  50. };  
  51.   
  52. #endif  

源文件:

[cpp]  view plain  copy
  1. #include "psa_usr_login.h"  
  2. #include   
  3. #include   
  4.   
  5. CUsrLogin::CUsrLogin( const QString& serverName, QWidget* parent /*= NULL*/ )  
  6.     : QDialog(parent)  
  7.     , mpServer(NULL)  
  8.     , mpTimeLine(NULL)  
  9. {  
  10.     ui.setupUi(this);  
  11.   
  12.     mIndex = 1;  
  13.     mServerName = serverName;  
  14.   
  15.     QButtonGroup* btnGroup = new QButtonGroup;  
  16.     btnGroup->addButton(ui.btn_showCurPro,  PROCESS_SHOW);  
  17.     btnGroup->addButton(ui.btn_openNewPro,  PROCESS_RESTART);  
  18.   
  19.     ui.progressBar->setVisible(false);  
  20.     mpTimeLine = new QTimeLine(3000, this);  
  21.     mpTimeLine->setFrameRange(0, 100);  
  22.     connect(mpTimeLine, SIGNAL(frameChanged(int)), ui.progressBar, SLOT(setValue(int)));  
  23.     connect(mpTimeLine, SIGNAL(finished()), this, SLOT(slot_timeFinished()));  
  24.   
  25.     connect(btnGroup, SIGNAL(buttonPressed(int)), this, SLOT(slot_btnGroupClicked(int)));  
  26.     connect(ui.btn_ok, SIGNAL(clicked()), this, SLOT(slot_ok()));  
  27.     connect(ui.btn_cancel, SIGNAL(clicked()), this, SLOT(slot_cancel()));  
  28. }  
  29.   
  30. CUsrLogin::~CUsrLogin()  
  31. {  
  32.     if(mpServer)  
  33.     {  
  34.         QLocalServer::removeServer(mServerName);  
  35.         delete mpServer;  
  36.         mpServer = NULL;  
  37.     }  
  38.   
  39.     if(mpTimeLine)  
  40.     {  
  41.         mpTimeLine->stop();  
  42.         delete mpTimeLine;  
  43.         mpTimeLine = NULL;  
  44.     }  
  45. }  
  46.   
  47. int CUsrLogin::GetIndex() const  
  48. {  
  49.     return mIndex;  
  50. }  
  51.   
  52. void CUsrLogin::slot_ok()  
  53. {  
  54.     QLocalSocket ls;  
  55.     ls.connectToServer(mServerName);  
  56.   
  57.     if (ls.waitForConnected())  
  58.     {  
  59.         switch(mIndex)  
  60.         {  
  61.         case PROCESS_SHOW:  
  62.             {  
  63.                 char msg[25] = {0};  
  64.                 memcpy(msg, PRO_SHOW.toStdString().c_str(), PRO_SHOW.length());  
  65.                 ls.write(msg);  
  66.                 ls.waitForBytesWritten();  
  67.   
  68.                 QDialog::accept();  
  69.                 break;  
  70.             }  
  71.         case PROCESS_RESTART:  
  72.             {  
  73.                 char msg[25] = {0};  
  74.                 memcpy(msg, PRO_RESTART.toStdString().c_str(), PRO_RESTART.length());  
  75.                 ls.write(msg);  
  76.                 ls.waitForBytesWritten();  
  77.   
  78.                 ui.progressBar->setVisible(true);  
  79.                 mpTimeLine->start();  
  80.                 break;  
  81.             }  
  82.         case PROCESS_STOP:  
  83.             {  
  84.                 char msg[25] = {0};  
  85.                 memcpy(msg, PRO_STOP.toStdString().c_str(), PRO_STOP.length());  
  86.                 ls.write(msg);  
  87.                 ls.waitForBytesWritten();  
  88.   
  89.                 QDialog::accept();  
  90.                 break;  
  91.             }  
  92.         default:  
  93.             QDialog::accept();  
  94.             break;  
  95.         }  
  96.     }  
  97. }  
  98.   
  99. void CUsrLogin::slot_cancel()  
  100. {  
  101.     QDialog::reject();  
  102. }  
  103.   
  104. void CUsrLogin::slot_btnGroupClicked( int idx)  
  105. {  
  106.     mIndex = idx;  
  107. }  
  108.   
  109. void CUsrLogin::slot_readyRead()  
  110. {  
  111.     QLocalSocket *local = static_cast(sender());  
  112.     if (!local)  
  113.         return;  
  114.   
  115.     QTextStream in(local);  
  116.     QString     readMsg;  
  117.   
  118.     readMsg = in.readAll();  
  119.   
  120.     emit sig_newOrder(readMsg);  
  121. }  
  122.   
  123. // 判断是否有一个同名的服务器在运行  
  124. int CUsrLogin::IsServerRun(const QString & servername)  
  125. {          
  126.     QLocalSocket ls;  
  127.     ls.connectToServer(servername);  
  128.   
  129.     if (ls.waitForConnected(1000))   
  130.     {  
  131.         ls.disconnectFromServer();  
  132.         ls.close();  
  133.         return 1;  
  134.     }  
  135.   
  136.     return 0;  
  137. }  
  138.   
  139. bool CUsrLogin::InitServer()  
  140. {  
  141.     if (!IsServerRun(mServerName))  
  142.     {  
  143.         mpServer = new QLocalServer;  
  144.         QLocalServer::removeServer(mServerName);  
  145.   
  146.         mpServer->listen(mServerName);  
  147.         connect(mpServer, SIGNAL(newConnection()), this, SLOT(slot_newConnection()));  
  148.   
  149.         return true;  
  150.     }  
  151.   
  152.     return false;  
  153. }  
  154.   
  155. void CUsrLogin::slot_newConnection()  
  156. {  
  157.     QLocalSocket *newsocket = mpServer->nextPendingConnection();  
  158.     connect(newsocket, SIGNAL(readyRead()), this, SLOT(slot_readyRead()));  
  159. }  
  160.   
  161. void CUsrLogin::slot_timeFinished()  
  162. {  
  163.     if(InitServer())  
  164.     {  
  165.         QDialog::accept();  
  166.     }  
  167. }  

主函数:

在主函数中添加CUsrLogin.. 和 信号槽函数。

[cpp]  view plain  copy
  1. int main(int argc, char * argv[])  
  2. {  
  3.     QApplication app(argc, argv);  
  4.   
  5.     QString name = "******"// 自定义程序名称  
  6. "color:#ff0000;">   CUsrLogin login(name);  
  7.     if(!login.InitServer())  
  8.     {  
  9.         int ret = login.exec();  
  10.         if(QDialog::Accepted == ret)  
  11.         {  
  12.             if( login.GetIndex() == PROCESS_SHOW ||  
  13.                 login.GetIndex() == PROCESS_STOP )  
  14.             {  
  15.                 return 1;  
  16.             }  
  17.         }  
  18.         else  
  19.         {  
  20.             return 1;  
  21.         }  
  22.     }  
  23.   
  24.     MainWindow mainWin;  
  25.     mainWin.show();  
  26.   
  27.     "color:#ff0000;">QObject::connect(&login, SIGNAL(sig_newOrder(const QString&)), &mainWin, SLOT(slotProcAppMessage(const QString&)));  
  28.   
  29.     return app.exec();  
  30. }  


MainWindow中实现:

[cpp]  view plain  copy
  1. "color:#000000;">void MainWindow::slotProcAppMessage( const QString& order)  
  2. {  
  3.     if(order == PRO_SHOW)  
  4.     {  
  5.         #ifdef WIN32  
  6.         {  
  7.             activateWindow();  
  8.             showMinimized();  
  9.             showMaximized();  
  10.         }  
  11.         #else  
  12.         {  
  13.             activateWindow();  
  14.   
  15.             if(windowState () & Qt::WindowMinimized)  
  16.             {     
  17.                     setWindowState(windowState() & ~Qt::WindowMinimized | Qt::WindowActive);  
  18.                     showMaximized();  
  19.                     show();  
  20.             }  
  21.             else if(windowState() & Qt::WindowMaximized)  
  22.             {     
  23.                     setWindowState(windowState() & Qt::WindowMaximized | Qt::WindowActive);  
  24.             }     
  25.             else  
  26.             {     
  27.                     setWindowState(windowState() & Qt::WindowMaximized | Qt::WindowActive);  
  28.             }  
  29.         }  
  30.         #endif  
  31.     }  
  32.     else if(order == PRO_RESTART)  
  33.     {  
  34.         close();  
  35.     }  
  36.     else if(order == PRO_STOP)  
  37.     {  
  38.         close();  
  39.     }  
  40. }  

3. QSingleApplication类

实现原理应该和QLocalServer和QLocalSocket相同。

使用Qt中的QSharedMemory,QLocalServer和QLocalSocket实现(不过需要在你的.pro里加上QT += network)

具体说明可以参考:

http://blog.csdn.net/playstudy/article/details/7796691 


你可能感兴趣的:(Qt)