正常用qt做完一个程序之后,会发现仍然有许多小的问题,比如,在打开做好的程序之后,再次点击exe文件,仍能再次打开一个新的,这样就有两个一样的程序在运行,这并不是开发者想要的现象,也是为了避免让用户找到一些bug,所以,本博就介绍一下如何让你的程序只能运行一个。
本次实验环境是在MSVC编译器上运行的,qt5.10.0,本文与 环境无关
惯例附上参考链接:https://blog.csdn.net/xqhrs232/article/details/81018037
https://cloud.tencent.com/developer/article/1431915
在网上,讲解这个 还是蛮多的, 方式也有挺多,但大都分为三种方式,这里我只用2种最简单的方式来实现,即共享内存方式和QtSingleApplication 方式。
共享内存方式 :
在main函数如下
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CommonHelper::setStyle(":/qss/white.qss");//默认一个主题风格
//QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB2312"));
//QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));
QSharedMemory mem("untitled");//以系统exe名称为参数,定义共享内存mem
if(!mem.create(1))//创建共享内存mem,如果该共享内存已存在,则弹出提示对话框,并退出
{
QMessageBox::information(0,QObject::tr("Warning"),QObject::tr("An instance is running"));
return 0;
}
MainWindow w;
w.show();
return a.exec();
}
然后release运行一遍之后打包程序,连续点击exe运行,就可以 发现点击第一次程序被打开,之后点击就会弹出提示框 “已经运行”英文,所以这种方式既简单 实现,又不用加一堆其余代码,很方便。
使用共享内存方式,当第二个进程启动时,判断内存区数据是否建立,如有,则退出; 这种方式有弊端,在程序发生崩溃时,未及时清除共享区数据,导致程序不能正常启动。
QtSingleApplication 方式:(用定时器实现)
mainwindow.h加上如下程序
#include
#include
class SingleApplication : public QApplication
{
Q_OBJECT
public:
SingleApplication(int &argc, char *argv[], const QString uniqueKey);
bool isRunning();
bool sendMessage(const QString &message);
public slots:
void checkForMessage();
void receiveMessage(QString &message);
signals:
void messageAvailable(QString message);
private:
bool _isRunning;
QSharedMemory sharedMemory;
};
mian.cpp加上如下程序:
#include "mainwindow.h"
#include
#include
//#include
#include
#include
#include
int main(int argc, char *argv[])
{
///共享内存方式
/*QApplication a(argc, argv);
//QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB2312"));
//QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));
QSharedMemory mem("untitled");//以系统exe名称为参数,定义共享内存mem
if(!mem.create(1))//创建共享内存mem,如果该共享内存已存在,则弹出提示对话框,并退出
{
QMessageBox::information(0,QObject::tr("Warning"),QObject::tr("An instance is running"));
return 0;
}
CommonHelper::setStyle(":/qss/white.qss");
MainWindow w;
w.show();
return a.exec();
*/
///SingleApplication方式
SingleApplication app(argc, argv, "some unique key string");
if (app.isRunning())
{
QMessageBox::information(NULL, "GLMPlayer",
"Your GLMPLayer is already running ...",
QMessageBox::Ok);
app.sendMessage("message from other instance.");
return 0;
}
MainWindow *mainWindow = new MainWindow();
// connect message queue to the main window.
QObject::connect(&app, SIGNAL(messageAvailable(QString)), mainWindow, SLOT(receiveMessage(QString)));
CommonHelper::setStyle(":/qss/white.qss");
mainWindow->show();
return app.exec();
}
//改变全局按钮风格,工业模式风格
/*a.setStyleSheet("QPushButton{min-height:50px; min-width: 80px; background:#DDDDDD; border-right:2px solid #646464; border-bottom:2px solid #646464; "
"border-left:2px solid #FFFFFF; border-top:2px solid #FFFFFF; border-radius:2px;}"
"QPushButton:disabled{min-height:50px; min-width: 50px; background:#DDDDDD; border-right:2px solid #FFFFFF; border-bottom:2px solid #FFFFFF; "
"border-left:2px solid #646464; border-top:2px solid #646464; border-radius:2px;}"
"QPushButton:pressed{min-height:50px; min-width: 50px; background:#DDDDDD; border-right:2px solid #FFFFFF; border-bottom:2px solid #FFFFFF; "
"border-left:2px solid #646464; border-top:2px solid #646464; border-radius:2px;}"
);*/
SingleApplication::SingleApplication(int &argc, char *argv[], const QString uniqueKey) : QApplication(argc, argv)
{
sharedMemory.setKey(uniqueKey);
if (sharedMemory.attach())
_isRunning = true;
else
{
_isRunning = false;
// attach data to shared memory.
QByteArray byteArray("0"); // default value to note that no message is available.
if (!sharedMemory.create(byteArray.size()))
{
qDebug("Unable to create single instance.");
return;
}
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = byteArray.data();
memcpy(to, from, qMin(sharedMemory.size(), byteArray.size()));
sharedMemory.unlock();
// start checking for messages of other instances.
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(checkForMessage()));
timer->start(1000);
}
}
// public slots.
void SingleApplication::checkForMessage()
{
sharedMemory.lock();
QByteArray byteArray = QByteArray((char*)sharedMemory.constData(), sharedMemory.size());
sharedMemory.unlock();
if (byteArray.left(1) == "0")
return;
byteArray.remove(0, 1);
QString message = QString::fromUtf8(byteArray.constData());
emit messageAvailable(message);
// remove message from shared memory.
byteArray = "0";
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = byteArray.data();
memcpy(to, from, qMin(sharedMemory.size(), byteArray.size()));
sharedMemory.unlock();
}
// public functions.
bool SingleApplication::isRunning()
{
return _isRunning;
}
bool SingleApplication::sendMessage(const QString &message)
{
if (!_isRunning)
return false;
QByteArray byteArray("1");
byteArray.append(message.toUtf8());
byteArray.append('/0'); // < should be as char here, not a string!
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = byteArray.data();
memcpy(to, from, qMin(sharedMemory.size(), byteArray.size()));
sharedMemory.unlock();
return true;
}
void SingleApplication::receiveMessage(QString &message)
{
QMessageBox::information(NULL, "GLMPlayer",
"Your GLMPLayer is already running ...",
QMessageBox::Ok);
}
关于再次点击exe,程序置顶到窗口最顶层部分:
暂未实现,寻求大佬给出解决方式~