qt之 使程序只运行一个实例,若再次点击exe则将已运行的实例置在最顶层显示

前言:

正常用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,程序置顶到窗口最顶层部分:

暂未实现,寻求大佬给出解决方式~

你可能感兴趣的:(#,qt数据处理/算法类,qt程序只能运行一个,qt运行唯一实例,qt只能打开一次)