Qt 防多开
来源:互联网 发布:java编程代码 编辑:程序博客网 时间:2024/05/16 12:26
防止多开传统的做法有文件锁(如Eclipse的.lock文件), 进程间通信等.
但是使用文件锁方式原实例无法知晓有新实例试图启动, 从而置顶自己的窗口.
进程间通信可以使用共享内存. 如使用启动中的腾讯qq来登录qq音乐.也可以使用server, socket这样讨巧的方法
Qt本身没有提供一个跨平台的防多开解决方案, 官方推荐的QSingleApplication解决方案并不包含在Qt的library中,并且貌似是遵从商业协议而非社区版本. 所以需要我们自己来实现一个.
使用共享内存和文件锁的一个缺点是,程序一旦异常退出, 可能导致下一次无法正常启动 (还记得要去手动删除Eclipse的.lock文件的时候吧)
而使用QLocalServer和QLocalSocket结合QSharedMemory可以很好的实现多开的检查以及对先前实例的唤醒.
参考链接:http://www.qtcentre.org/wiki/index.php?title=SingleApplication#Introduction
我的实际例子
// singleApplication.h
#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H
#include <QApplication>
#include <QSharedMemory>
#include <QLocalServer>
#include "dlgmain.h"
class SingleApplication : public QApplication
{
Q_OBJECT
public:
explicit SingleApplication(int &argc, char* argv[], const QString uniqueKey);
bool isRunning();
bool sendMessage(const QString & message);
public slots:
void receiveMessage();
void showMainWindow();
signals:
void messageAvailable(QString message);
private:
bool _isRunning;
QString _uniqueKey;
QSharedMemory sharedMemory;
QLocalServer* localServer;
static const int timeout = 1000;
};
#endif // SINGLEAPPLICATION_H
// singleApplication.cpp
#include "singleapplication.h"
#include <QLocalSocket>
/*
* CONSTRUCTION: set SingleApplication's shareMemory key to <uniqueKey>
* test attach , if success, already has an instance running
* if not running, use shareMemory to create a segment in the memory
* new a server to listem for <uniqueKey>, once received, hand over to SLOT(receiveMessage())
*
*/
SingleApplication::SingleApplication(int &argc, char* argv[], const QString uniqueKey) :
QApplication(argc, argv), _uniqueKey(uniqueKey)
{
sharedMemory.setKey(_uniqueKey);
if(sharedMemory.attach()){
_isRunning = true;
}
else{
_isRunning = false;
if(!sharedMemory.create(1)){
qDebug()<<"Unable to create single instance";
return;
}
// create local server and listener to incomming message from other instances.
localServer = new QLocalServer(this);
// connect(localServer, SIGNAL(newConnection()), this, SLOT(receiveMessage()));
connect(localServer, SIGNAL(newConnection()), this, SLOT(showMainWindow()));
localServer->listen(_uniqueKey);
}
}
// public slot
/*
* RECIVER: waiting for connection.once get one connection, create a socket to communicate with the client.
*
*/
void SingleApplication::receiveMessage(){
qDebug()<<"receiveMessage";
QLocalSocket* localSocket = localServer->nextPendingConnection();
if(!localSocket->waitForReadyRead(timeout)){
qDebug()<<"localSocket waitForReadyRead failed.";
qDebug()<<localSocket->errorString().toLatin1();
return;
}
QByteArray byteArray = localSocket->readAll();
QString message = QString::fromUtf8(byteArray.constData());
emit messageAvailable(message);
localSocket->disconnectFromServer();
}
void SingleApplication::showMainWindow(){
QLocalSocket *localSocket = localServer->nextPendingConnection();
if (!localSocket)
return;
delete localSocket;
DlgMain::shareInstance()->show();
}
// public functions;
bool SingleApplication::isRunning(){
qDebug()<<"SingleApplication is running? "<<_isRunning;
return _isRunning;
}
/*
* SENDER: if there is already a instance running, create a Socket to communicate with It's Server.
*
*/
bool SingleApplication::sendMessage(const QString &message){
qDebug()<<"sendMessage";
if(!_isRunning){
return false;
} // no instance, do nothing.
QLocalSocket localSocket(this);
localSocket.connectToServer(_uniqueKey, QIODevice::WriteOnly);
if(!localSocket.waitForConnected(timeout)){
qDebug()<<"waitForConnected";
qDebug()<<localSocket.errorString().toLatin1();
return false;
}
if(!localSocket.waitForBytesWritten(timeout)){
qDebug()<<"waitForBytesWritten";
qDebug()<<localSocket.errorString().toLatin1();
return false;
}
localSocket.disconnectFromServer();
return true;
}
使用方式:(直接把上面的类拷去用就行,)
// 注意一下main.cpp的调用以及槽的使用就行
#include "dlglogin.h"
#include "singleapplication.h"
int main(int argc, char *argv[])
{
SingleApplication app(argc, argv, "CocosPlay");
if(app.isRunning()) {
app.sendMessage("call");
return 0;
}
QObject::connect(&app, SIGNAL(messageAvailable(QString)), &app, SLOT(showMainWindow()));
DlgLogin* mainWindow = DlgLogin::shareInstance();
mainWindow->show();
mainWindow->on_btnLogin_clicked();
return app.exec();
}
0 0
- Qt 防多开
- QT
- QT
- QT
- Qt
- qt
- QT
- QT
- QT
- QT
- qt
- Qt
- QT
- qt
- qt
- Qt
- Qt
- QT
- BZOJ 1190 HNOI2007 梦幻岛宝珠 动态规划
- hdu 4006 The kth great number
- VMware ESXI 5.5基础安装与网络配置
- uboot的链接基地址
- UVA 10767-Barcelona’s trams(DP+数学推导)
- Qt 防多开
- 如何解决ubuntu下找不到libgtk-x11-2.0.so.0
- LoadRunner的两个不一致(Controller和Analysis;Summary Peport和Graphs-Average Transaction Response )
- 腾讯2015实习生招聘---内推,提前批 腾讯2015实习生招聘TST计划,寻找下一代互联网精英
- 矩阵乘法
- swift UI专项训练11 ActionSheet
- nodejs qt笔记
- lnmp环境配置
- C++中的单例模式