qtSingleApplication使用总结

开发应用程序的时候,经常会有“只允许运行一个实例”这样的需求。QtSolution中,提供了qtsingleapplication和qtsignlecoreapplication,用于实现程序单例运行。

下面以一个窗体应用为例,阐述qtsignleapplication的一些使用心得。


不考虑单例执行,main函数大致是这样的结构

#include <QApplicaton>
#include "FrmMain.h"     // 主窗体, QMainWindow 或者是 QWidget 之类
int main(int argc, char** argv)

{
    QApplication app(argc, argv);
    // 主窗体初始化并显示   
    FrmMain frm;
    frm.show();
    return app.exec();

}

如果使用qtsingleapplication以实现单例执行,代码只需稍微修改下

#include <qtsingleapplication.h>
#include "FrmMain.h"
int main(int argc, char** argv)
{
    const QString APP_ID("app id");   // 自定义的程序标记,由这个标记去区别实例。如果不指定,则会以qApp->applicationFilePath()做为标记
    QtSingleApplicion app(APP_ID, argc, argv);
    if(app.isRunning()) {
    // 如果已经有实例运行
    return -1;
    }
    FrmMain frm;
    frm.show();
    return app.exec();
}

这是最基本的使用,就是用APP_ID标记这个程序,运行时先判断是否已经有实例在运行,如果有则退出,没有的话就执行主窗体的初始化和现实,进入事件循环。

心得1:

单例执行一般有两种需求,1种是在本机上,这个程序最多只能运行一个实例,1种是,本机上该exe文件对应的程序只能运行一个实例,但是如果别的位置还有该exe的实例,另外别的该exe实例也可以运行。如果需求是前者,那么就用一个固定的字符串作为标记,无论本机上有多少个该应用程序副本,同时最多也只能有一个实例在运行。如果是需求2,则使用exe对应的路径作为APP_ID。

需要说明的是,实现单例运行的逻辑是根据APP_ID,在临时目录下存在一个对应于APP_ID的文件。如果开启了一个实例,然后删除对应的文件,然后就可以再次开启一个实例。

特别需要说明的是,如果是在linux开发,涉及到局域网内远程计算机的执行该程序,无论是使用固定字符串还是文件路径作为APP_ID做为标记都会导致本机、远程计算机同时只能运行一个实例。但有时需求并不是这样,而是一个终端可以有一个实例运行,那么这时, 把APP_ID的参数加上远程访问的计算机IP信息加上。

心得2:

上面的例子简单粗暴的处理,如果已存在运行的实例,就退出。实际应用中往往需要执行的是如果有实例在运行,要么给出提示信息,要么直接把正在运行的实例的窗口显示出来。

QtSingleApplication提供了一个public slots: bool sendMessage(const QString& message, int timeout = 5000);和一个信号void messageReceived(const QString& message);

那么逻辑就应该是这样的,

a. 判断是否有实例在运行 b.如果有,则发送一条信息 c.主窗体有个槽函数与QtSingleApplication的messageReceived的信号连接起来,当有程序运行时发现已经有实例运行时,发动了信息,已运行的实例接收到信息就会发送messageReceived的信号,从而去实行主窗体的槽函数。

我在具体使用的时候,会把程序运行的路径作为信息传递,这样主窗体的槽函数可以对这个路径参数判断,判断是否和自己所在实例的路径一致,如果一致则主窗体前端显示,否则不一致,说明是别的路径下的执行程序,然后给出提示信息。

另外,主窗体对应的槽函数如果是简单的show(),主窗体会被激活,并显示出来,但是可能不是会在最前端显示。我一般会临时更改主窗体的windowsflag属性,添加最前端显示的flag,然后显示,然后取消掉最前端显示的flag,然后再显示。这样就会保证窗体是在最前端显示。特别说明的是,取消最前端显示的flag后,必须再执行show,否则窗体会隐藏不显示.代码示例如下:

void FrmMain::sltMessageReceived(const QString &msg)
{
    Qt::WindowFlags flags = windowFlags();
    flags |= Qt::WindowStaysOnTopHint;
    setWindowFlags(flags);
    show();
    flags &= ~Qt::WindowStaysOnTopHint;
    setWindowFlags(flags);
    showNormal();
    if(msg != qApp->applicationFilePath()) {
        const QString& warnStr(tr("Only on instance is allowed. Close running application first."));
        QMessageBox::warning(this, tr("Warn"), warnStr, QMessageBox::Ok);
    }
}

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值