[Qt学习笔记]Qt实现程序单例运行,再次点击后弹出界面

一、介绍

在实际工程项目中,软件在打开情况下,再次打开软件会出现打开多个软件界面的情况,进而找出与下位机交互的错误,对于工程项目是不允许此类情况出现,所以在软件运行时必须保证该软件是单例运行,在运行状况下再次打开时进行提示或弹出之前的软件界面。

二、实现方法

2.1 重写QApplation类本地localserver监控单例程序

2.1.1 实现原理

通过socket通讯实现程序单实例运行,已程序名称创建一个localServer,通过socket一直监听程序是否在运行。当程序在运行时,再次打软件,将激活显示已运行的程序显示界面。

2.1.2 效果展示

20.SingleApplationTest.gif

2.1.3 实现代码

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)
{
    //取应用程序名作为localServer的名字
    serverName = QFileInfo(QApplication::applicationFilePath()).fileName();
    InitLocalConnection();
}


/*****************************************************************
* 检查是否已有一个实例在运行, true有实例运行, false没有实例运行.
******************************************************************/
bool SingleApplication::isRunning()
{
    return isRunnings;
}


/*****************************************************************
* 通过socket通讯实现程序单实例运行,监听到新的连接时触发该函数.
******************************************************************/
void SingleApplication::NewLocalConnection()
{
    QLocalSocket *localSocket = localserver->nextPendingConnection();
    if(localSocket)
    {
        localSocket->waitForReadyRead(TIME_OUT * 2);
        delete localSocket;

        //其他处理,如:读取启动参数
        ActivateWindow();
    }
}


/*****************************************************************
* 通过socket通讯实现程序单实例运行,
* 初始化本地连接,如果连接不上server,则创建,否则退出
******************************************************************/
void SingleApplication::InitLocalConnection()
{
    isRunnings = false;
    QLocalSocket socket;
    socket.connectToServer(serverName);
    if(socket.waitForConnected(TIME_OUT))
    {
        isRunnings = true;

        //其他处理,如:将启动参数发送到服务端
        return;
    }

    //连接不上服务器,就创建一个
    NewLocalServer();
}

/*****************************************************************
* 创建localserver
******************************************************************/
void SingleApplication::NewLocalServer()
{
    localserver = new QLocalServer(this);
    connect(localserver, &QLocalServer::newConnection, this, &SingleApplication::NewLocalConnection);
    if(!localserver->listen(serverName))
    {
        // 此时监听失败,可能是程序崩溃时,残留进程服务导致的,移除
        if(localserver->serverError() == QAbstractSocket::AddressInUseError)
        {
            localserver->removeServer(serverName);
            localserver->listen(serverName); //重新监听
        }
    }
}

/*****************************************************************
* 激活主窗口
******************************************************************/
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[]);
    // 判断是否已有实例在运行
    bool isRunning();
    QWidget *w;

private slots:
    //有新连接时触发
    void NewLocalConnection();

private:
    //初始化本地连接
    void InitLocalConnection();
    //创建服务端
    void NewLocalServer();
    //激活窗口
    void ActivateWindow();

    // 本地socket Server
    QLocalServer *localserver;
    // 服务名称
    QString       serverName;
    // 运行状态
    bool          isRunnings;
};

#endif // SINGLEAPPLICATION_H

main函数调用,将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 实现原理

文件锁试下程序单例运行,就是在程序启动的时候创建一个唯一标识的文件锁文件,再次启动程序时先检测是都有文件锁存在,且文件锁是否有效来达到锁定程序的效果。

2.2.2 效果展示

单实例测试.gif

2.2.3 实现代码

#include "widget.h"
//#include "singleapplication.h"
#include <QApplication>
#include <QLockFile>
#include <QMessageBox>

bool CheckSoftExist()
{
    // 防止程序重复启动
    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上,大家学习交流,有错误或bug还望不吝赐教,希望大脚给个星星支持一下。
https://gitee.com/Damion_Learning/QtHalcon_LearningRecord.git

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt实现点击按钮弹一个新界面,你需要以下步骤: 1. 创建一个新的 QWidget 类,作为你要弹的新界面。 2. 在 QWidget 类中添加你需要的控件,比如按钮、文本框等。 3. 在主窗口中创建一个 QPushButton 控件,并将其添加到布局中。 4. 为 QPushButton 控件添加一个槽函数,在槽函数中创建新的 QWidget 对象,并显示它。 下面是一个简单的示例代码: ```cpp // 新界面类 class NewWidget : public QWidget { public: NewWidget(QWidget *parent = nullptr) : QWidget(parent) { // 添加控件 QLabel *label = new QLabel("Hello, World!", this); label->setAlignment(Qt::AlignCenter); label->setStyleSheet("font-size: 20px;"); } }; // 主窗口类 class MainWindow : public QMainWindow { public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { // 添加按钮 QPushButton *button = new QPushButton("Click me", this); connect(button, &QPushButton::clicked, this, &MainWindow::onButtonClick); setCentralWidget(button); } private slots: void onButtonClick() { // 弹界面 NewWidget *newWidget = new NewWidget(this); newWidget->setWindowTitle("New Widget"); newWidget->show(); } }; // 应用程序入口 int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow window; window.show(); return app.exec(); } ``` 在这个示例中,我们创建了一个 NewWidget 类作为新界面,添加了一个 QLabel 控件,并设置了字体样式。在主窗口中,我们创建了一个 QPushButton 控件,并将其添加到中央部件中。然后,我们为按钮添加了一个槽函数 onButtonClick(),在这个函数中创建了一个 NewWidget 对象,并显示它。 当用户点击按钮时,程序会执行 onButtonClick() 函数,弹一个新的 NewWidget 界面

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值