一杜耙、介紹
在實(shí)際工程項(xiàng)目中,軟件在打開情況下拂盯,再次打開軟件會(huì)出現(xiàn)打開多個(gè)軟件界面的情況佑女,進(jìn)而找出與下位機(jī)交互的錯(cuò)誤,對(duì)于工程項(xiàng)目是不允許此類情況出現(xiàn)谈竿,所以在軟件運(yùn)行時(shí)必須保證該軟件是單例運(yùn)行团驱,在運(yùn)行狀況下再次打開時(shí)進(jìn)行提示或彈出之前的軟件界面。
二空凸、實(shí)現(xiàn)方法
2.1 重寫QApplation類本地localserver監(jiān)控單例程序
2.1.1 實(shí)現(xiàn)原理
通過socket通訊實(shí)現(xiàn)程序單實(shí)例運(yùn)行嚎花,已程序名稱創(chuàng)建一個(gè)localServer,通過socket一直監(jiān)聽程序是否在運(yùn)行呀洲。當(dāng)程序在運(yùn)行時(shí)贩幻,再次打軟件,將激活顯示已運(yùn)行的程序顯示界面两嘴。
2.1.2 效果展示
20.SingleApplationTest.gif
2.1.3 實(shí)現(xiàn)代碼
singleapplation.cpp
#include "SingleApplication.h"
#include <QtNetwork/QLocalSocket>
#include <QFileInfo>
#define TIME_OUT 500
SingleApplication::SingleApplication(int &argc, char *argv[])
:QApplication(argc, argv),
isRunnings(false),
w(NULL),
localserver(NULL)
{
//取應(yīng)用程序名作為localServer的名字
serverName = QFileInfo(QApplication::applicationFilePath()).fileName();
InitLocalConnection();
}
/*****************************************************************
* 檢查是否已有一個(gè)實(shí)例在運(yùn)行, true有實(shí)例運(yùn)行, false沒有實(shí)例運(yùn)行.
******************************************************************/
bool SingleApplication::isRunning()
{
return isRunnings;
}
/*****************************************************************
* 通過socket通訊實(shí)現(xiàn)程序單實(shí)例運(yùn)行,監(jiān)聽到新的連接時(shí)觸發(fā)該函數(shù).
******************************************************************/
void SingleApplication::NewLocalConnection()
{
QLocalSocket *localSocket = localserver->nextPendingConnection();
if(localSocket)
{
localSocket->waitForReadyRead(TIME_OUT * 2);
delete localSocket;
//其他處理,如:讀取啟動(dòng)參數(shù)
ActivateWindow();
}
}
/*****************************************************************
* 通過socket通訊實(shí)現(xiàn)程序單實(shí)例運(yùn)行丛楚,
* 初始化本地連接,如果連接不上server憔辫,則創(chuàng)建趣些,否則退出
******************************************************************/
void SingleApplication::InitLocalConnection()
{
isRunnings = false;
QLocalSocket socket;
socket.connectToServer(serverName);
if(socket.waitForConnected(TIME_OUT))
{
isRunnings = true;
//其他處理,如:將啟動(dòng)參數(shù)發(fā)送到服務(wù)端
return;
}
//連接不上服務(wù)器,就創(chuàng)建一個(gè)
NewLocalServer();
}
/*****************************************************************
* 創(chuàng)建localserver
******************************************************************/
void SingleApplication::NewLocalServer()
{
localserver = new QLocalServer(this);
connect(localserver, &QLocalServer::newConnection, this, &SingleApplication::NewLocalConnection);
if(!localserver->listen(serverName))
{
// 此時(shí)監(jiān)聽失敗,可能是程序崩潰時(shí),殘留進(jìn)程服務(wù)導(dǎo)致的,移除
if(localserver->serverError() == QAbstractSocket::AddressInUseError)
{
localserver->removeServer(serverName);
localserver->listen(serverName); //重新監(jiān)聽
}
}
}
/*****************************************************************
* 激活主窗口
******************************************************************/
void SingleApplication::ActivateWindow()
{
if(w)
{
w->raise();
// w->activateWindow();
w->showNormal();
}
}
singleapplation.h
#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H
#include <QObject>
#include <QWidget>
#include <QApplication>
#include <QtNetwork/QLocalServer>
class SingleApplication : public QApplication
{
Q_OBJECT
public:
SingleApplication(int &argc, char *argv[]);
// 判斷是否已有實(shí)例在運(yùn)行
bool isRunning();
QWidget *w;
private slots:
//有新連接時(shí)觸發(fā)
void NewLocalConnection();
private:
//初始化本地連接
void InitLocalConnection();
//創(chuàng)建服務(wù)端
void NewLocalServer();
//激活窗口
void ActivateWindow();
// 本地socket Server
QLocalServer *localserver;
// 服務(wù)名稱
QString serverName;
// 運(yùn)行狀態(tài)
bool isRunnings;
};
#endif // SINGLEAPPLICATION_H
main函數(shù)調(diào)用,將QApplation改成SingleApplation類
#include "widget.h"
#include "singleapplication.h"
//#include <QApplication>
int main(int argc, char *argv[])
{
// 方法一 本地socket 使用SingleApplication 代替原來的QApplication類
SingleApplication a(argc, argv);
if(!a.isRunning()){
Widget w;
a.w = &w;
w.show();
return a.exec();
}
}
2.2 文件鎖
2.2.1 實(shí)現(xiàn)原理
文件鎖試下程序單例運(yùn)行贰您,就是在程序啟動(dòng)的時(shí)候創(chuàng)建一個(gè)唯一標(biāo)識(shí)的文件鎖文件坏平,再次啟動(dòng)程序時(shí)先檢測(cè)是都有文件鎖存在,且文件鎖是否有效來達(dá)到鎖定程序的效果锦亦。
2.2.2 效果展示
單實(shí)例測(cè)試.gif
2.2.3 實(shí)現(xiàn)代碼
#include "widget.h"
//#include "singleapplication.h"
#include <QApplication>
#include <QLockFile>
#include <QMessageBox>
bool CheckSoftExist()
{
// 防止程序重復(fù)啟動(dòng)
QString lockFilePath;
lockFilePath = "./singleApp.lock";
QLockFile *lockFile = new QLockFile(lockFilePath);
if (!lockFile ->tryLock(2000)) {
QMessageBox::warning(NULL, QObject::tr("Warning"), QObject::tr("The software is running!"));
return false;
}
return true;
}
int main(int argc, char *argv[])
{
// 方法一 本地socket 使用SingleApplication 代替原來的QApplication類
// SingleApplication a(argc, argv);
// if(!a.isRunning()){
// Widget w;
// a.w = &w;
// w.show();
// return a.exec();
// }
// 方法二 文件鎖方法
QApplication a(argc, argv);
if(CheckSoftExist() == true)
{
Widget w;
w.show();
return a.exec();
}
}
三舶替、源碼開源
源碼放到gitee上,大家學(xué)習(xí)交流杠园,有錯(cuò)誤或bug還望不吝賜教顾瞪,希望大腳給個(gè)星星支持一下。
https://gitee.com/Damion_Learning/QtHalcon_LearningRecord.git