首页 > 系统相关 >Qt 进程保活(开源,国产环境)QTableWidget列表

Qt 进程保活(开源,国产环境)QTableWidget列表

时间:2024-10-24 15:46:08浏览次数:7  
标签:WatchColumn Qt void QTableWidget 保活 tableWidget ui QString strPath

效果图

在这里插入图片描述

第一步 设计器

在这里插入图片描述
拖拽一个QTableWidget和三个QPushButton,布局一下

第二步 上码

1.mainwindow.h

代码如下(示例):

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QPushButton>
#include <QLabel>
#include <QFileInfo>
#include <QEvent>
#include <QCloseEvent>
#include "keeplivemanager.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void initView();

    void showView();

private slots:
    void onTableBtnClicked();
    void recvStatSignal(const QString &str1, const QString &str2);

    void on_pushButton_update_clicked();

    void on_pushButton_start_clicked();

    void on_pushButton_stop_clicked();

protected:
    // 重写关闭事件
    void closeEvent(QCloseEvent *event) override ;
    // 重写变形事件
    void resizeEvent(QResizeEvent *event) override;

private:
    Ui::MainWindow *ui;
    QMap<QString,QString> m_mapApps;
    KeepliveManager* m_pKeeplive = nullptr;


};
#endif // MAINWINDOW_H

2.mainwindow.cpp

代码如下(示例):

#include "mainwindow.h"
#include "ui_mainwindow.h"

enum   WatchColumn{
    _NAME     =0,
    _PATH     =1,
    _PID      =2,
    _STAT     =3,
    _EXEC     =4
};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle(tr("MyWatchDog"));
    initView();

    m_pKeeplive = new KeepliveManager();
    m_pKeeplive->Start();
    showView();
    QObject::connect(m_pKeeplive, &KeepliveManager::sendStatSignal, this, &MainWindow::recvStatSignal);
    m_pKeeplive->Watchasyn();

}

MainWindow::~MainWindow()
{
    delete m_pKeeplive;
    m_pKeeplive = nullptr;
    delete ui;
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    // 不执行默认关闭行为
    //event->ignore();
    // 最小化窗口 点击托盘"主界面"显示
    //this->hide();
}
void MainWindow::resizeEvent(QResizeEvent *event)
{
    int nWidth = this->width() - 20;
    ui->tableWidget->setColumnCount(5);
    ui->tableWidget->setColumnWidth(WatchColumn::_NAME, nWidth * 0.2);
    ui->tableWidget->setColumnWidth(WatchColumn::_PATH, nWidth * 0.4);
    ui->tableWidget->setColumnWidth(WatchColumn::_PID, nWidth * 0.1);
    ui->tableWidget->setColumnWidth(WatchColumn::_STAT, nWidth * 0.1);
    ui->tableWidget->setColumnWidth(WatchColumn::_EXEC, nWidth * 0.2);
}
void MainWindow::initView()
{
    int nWidth = this->width() - 20;
    ui->tableWidget->setColumnCount(5);
    ui->tableWidget->setColumnWidth(WatchColumn::_NAME, nWidth * 0.2);
    ui->tableWidget->setColumnWidth(WatchColumn::_PATH, nWidth * 0.4);
    ui->tableWidget->setColumnWidth(WatchColumn::_PID, nWidth * 0.1);
    ui->tableWidget->setColumnWidth(WatchColumn::_STAT, nWidth * 0.1);
    ui->tableWidget->setColumnWidth(WatchColumn::_EXEC, nWidth * 0.2);
    // 设置列标题
    ui->tableWidget->setHorizontalHeaderItem(WatchColumn::_NAME, new QTableWidgetItem(tr("应用")));
    ui->tableWidget->setHorizontalHeaderItem(WatchColumn::_PATH, new QTableWidgetItem(tr("路径")));
    ui->tableWidget->setHorizontalHeaderItem(WatchColumn::_PID, new QTableWidgetItem(tr("PID")));
    ui->tableWidget->setHorizontalHeaderItem(WatchColumn::_STAT, new QTableWidgetItem(tr("状态")));
    ui->tableWidget->setHorizontalHeaderItem(WatchColumn::_EXEC, new QTableWidgetItem(tr("操作")));
    ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    //ui->tableWidget->setSelectionMode(QAbstractItemView::MultiSelection);

    ui->tableWidget->verticalHeader()->setVisible(false);
    ui->tableWidget->horizontalHeader()->setStretchLastSection(true);

    connect(ui->tableWidget, &QTableWidget::itemPressed, this, [&](QTableWidgetItem *item){

    });


}
void MainWindow::showView()
{
    ui->tableWidget->clearContents();
    m_mapApps = m_pKeeplive->GetMap();
    int nIndex = 0;
    for (auto it = m_mapApps.begin(); it != m_mapApps.end(); ++it) {
        ui->tableWidget->setRowCount(nIndex + 1);
        QString strPath = it.key();
        QFileInfo fileInfo(strPath);
        QString strName = fileInfo.fileName();
        qDebug() << strName << strPath;

        ui->tableWidget->setItem(nIndex, WatchColumn::_NAME, new QTableWidgetItem(strName));
        QTableWidgetItem *itemPath = new QTableWidgetItem(strPath);
        itemPath->setToolTip(strPath);
        ui->tableWidget->setItem(nIndex, WatchColumn::_PATH, itemPath);
        ui->tableWidget->setItem(nIndex, WatchColumn::_PID, new QTableWidgetItem("0"));

        //状态
        QLabel *label3 = new QLabel("");
        QWidget *widget3 = new QWidget();
        QHBoxLayout *layout3 = new QHBoxLayout(widget3);
        layout3->addWidget(label3);
        layout3->setContentsMargins(8, 2, 8, 2);
        widget3->setLayout(layout3);
        ui->tableWidget->setCellWidget(nIndex, WatchColumn::_STAT, widget3);

        //操作
        QPushButton *button4 = new QPushButton(tr("停止"));
        button4->setStyleSheet("background-color: rgb(247, 211, 60);"
                               "color:rgb(255, 255, 255) ;"
                               "font-family: PingFang SC;"
                               "font-weight: bold;"
                               "font-size: 18px;");
        //设置按钮的自定义属性
        button4->setProperty("S_Name",strName);
        button4->setProperty("S_Path",strPath);
        connect(button4, SIGNAL(clicked(bool)), this, SLOT(onTableBtnClicked()));
        QWidget *widget4 = new QWidget();
        QHBoxLayout *layout4 = new QHBoxLayout(widget4);
        layout4->addWidget(button4);
        layout4->setContentsMargins(2, 2, 2, 2);
        widget4->setLayout(layout4);
        ui->tableWidget->setCellWidget(nIndex, WatchColumn::_EXEC, widget4);

        nIndex++;
    }

}

void MainWindow::onTableBtnClicked()
{
    QPushButton *button = (QPushButton*)sender();
    //提取按钮的自定义属性 数据类型须统一
    QString S_Name = button->property("S_Name").toString();
    QString S_Path = button->property("S_Path").toString();
    if(m_pKeeplive)
    {
        QString strText = button->text();
        if(strText == "开启")
        {
            m_pKeeplive->StartProcess(S_Path);
        }
        else
        {
            m_pKeeplive->StopProcess(S_Path);
        }
    }


}
void MainWindow::recvStatSignal(const QString &str1, const QString &str2)
{
    QString strPath = str1;
    QString strPid = str2;
    for (int row = 0; row < ui->tableWidget->rowCount(); ++row) {
        QTableWidgetItem *item = ui->tableWidget->item(row, WatchColumn::_PATH);
        if (item && item->text() == strPath) {
            // 更新
            QTableWidgetItem *item = new QTableWidgetItem(strPid);
            ui->tableWidget->setItem(row, WatchColumn::_PID, item);
            // 获取所在的 QWidget
            QWidget *widget3 = ui->tableWidget->cellWidget(row, WatchColumn::_STAT);
            QWidget *widget4 = ui->tableWidget->cellWidget(row, WatchColumn::_EXEC);
            if (widget3 && widget4) {
                //获取button
                QPushButton *button = widget4->findChild<QPushButton *>();
                //获取label
                QLabel *label = widget3->findChild<QLabel *>();
                if (button && label) {
                    if(strPid.isEmpty() || strPid == "0")
                    {
                        button->setText(tr("开启"));
                        QString strStyleSheet = QString("background-color: rgb(255, 0, 0);  border-radius: %1px;").arg(label->height()/2);
                        label->setStyleSheet(strStyleSheet);
                    }
                    else
                    {
                        button->setText(tr("停止"));
                        QString strStyleSheet = QString("background-color: rgb(0, 170, 127);  border-radius: %1px;").arg(label->height()/2);
                        label->setStyleSheet(strStyleSheet);
                    }

                }
            }
        }
    }

}

void MainWindow::on_pushButton_update_clicked()
{
    ui->tableWidget->clearSelection();
    if(m_pKeeplive)
    {
        m_pKeeplive->UpdateProcess();
    }
}

void MainWindow::on_pushButton_start_clicked()
{
    ui->tableWidget->clearSelection();
    if(m_pKeeplive)
    {
        m_pKeeplive->StartProcess("");
    }
}

void MainWindow::on_pushButton_stop_clicked()
{
    ui->tableWidget->clearSelection();
    if(m_pKeeplive)
    {
        m_pKeeplive->StopProcess("");
    }
}


3.keeplivemanager.h

代码如下(示例):

#ifndef KEEPLIVEMANAGER_H
#define KEEPLIVEMANAGER_H

#include <QObject>
#include <QProcess>
#include <QThread>
#include <QMap>
#include <QDebug>
#include <thread>
#include <QMutex>
struct stAppStat
{
    QString strPath;
    QString strType;
    int  nKeeping; //是否需要保活 1是 0否
    stAppStat( const QString &path = "", const QString &type = "", int keeping = 0)
        : strPath(path), strType(type), nKeeping(keeping) {}
};

class KeepliveManager : public QObject
{
    Q_OBJECT

public:
    explicit KeepliveManager(QObject *parent = nullptr);
    virtual ~KeepliveManager();

    //开始+读取配置
    void Start();
    //停止循环
    void Stop();

    //检测+启动
    void Watch();
    //异步执行
    void Watchasyn();

    void SetMap(const QMap<QString,QString>& map);

    QMap<QString,QString> GetMap();

    void StartProcess(const QString &path);
    void StopProcess(const QString &path);
    //刷新
    void UpdateProcess();

signals:
    void sendStatSignal(const QString &str1, const QString &str2);

private:
    //判断进程是否存在
    bool isProcessRunning(const QString &processName,QString &processPid);
private:
    bool bkeeping_  = true;
    bool bruning_   = true;
    int  nYesCount_   = 0;
    int  nNoCount_    = 0;
    QMutex m_mutex;   //定义一个互斥锁变量
    QMap<QString,stAppStat*> m_mapApps;

};

#endif // KEEPLIVEMANAGER_H

4.keeplivemanager.cpp

代码如下(示例):

#include "keeplivemanager.h"

KeepliveManager::KeepliveManager(QObject *parent)
    : QObject(parent), bkeeping_(true), bruning_(true)
{

}
KeepliveManager::~KeepliveManager()
{
    for (auto it = m_mapApps.begin(); it != m_mapApps.end(); ++it) {
        QString strPath = it.key();
        stAppStat* stStat = it.value();
        delete stStat;
        stStat = nullptr;
    }
    m_mapApps.clear();
}

bool KeepliveManager::isProcessRunning(const QString &processName,QString &processPid)
{
    QProcess process;
    // 设置环境变量,确保可以在PATH中找到pidof命令
    process.setEnvironment(QProcess::systemEnvironment());

    // 执行pidof命令,并获取输出
    process.start("pidof", QStringList() << processName);
    process.waitForFinished();

    QByteArray output = process.readAllStandardOutput();
    processPid = output.trimmed();
    // 如果输出为空,则表示没有找到对应的进程
    return !output.trimmed().isEmpty();
}
void KeepliveManager::Stop()
{
    qDebug()<< " stop" ;
    bkeeping_ = false;
    bruning_ = false;
}
void KeepliveManager::UpdateProcess()
{
    QMutexLocker locker(&m_mutex);
    for (QMap<QString, stAppStat*>::const_iterator it = m_mapApps.begin(); it != m_mapApps.end(); ++it)
    {
        QString strPath = it.key();
        stAppStat* stStat = it.value();
        if(stStat->nKeeping == 0)
        {
            nNoCount_++;
            if(nNoCount_ > 5)
            {
                qDebug() << strPath << " is not keeping";
                nNoCount_ = 0;
            }
            continue;
        }
        QString strPid ;
        bool _bRet = isProcessRunning(strPath,strPid);
        emit sendStatSignal(strPath,strPid);
        if(_bRet)
        {
            nYesCount_++;
            if(nYesCount_ > 10)
            {
				qDebug() << strPath << " is not running";
                nYesCount_ = 0;
            }
        }
        else
        {
            QProcess::startDetached(strPath + stStat->strType);
        }
    }

}
void KeepliveManager::SetMap(const QMap<QString,QString>& map)
{
    for (auto it = map.begin(); it != map.end(); ++it) {
        stAppStat* stStat = new  stAppStat();
        stStat->strPath =  it.key();
        stStat->strType = it.value();
        stStat->nKeeping = 1;
        m_mapApps.insert(it.key(),stStat);
    }

}
QMap<QString,QString> KeepliveManager::GetMap()
{
    QMap<QString,QString> _map;
    for (auto it = m_mapApps.begin(); it != m_mapApps.end(); ++it) {
        QString strPath = it.key();
        stAppStat* stStat = it.value();
        _map.insert(strPath, stStat->strType);
    }
    return _map;
}
void KeepliveManager::Start()
{
    qDebug()<< " start" ;
    bkeeping_ = true;
    bruning_ = true;
    if(m_mapApps.size() == 0)
    {
		//拓展成从配置文件中读取
        int sub_count = 1;
        for(int n = 0 ; n < sub_count ;n++ )
        {
            QString strIndex = "/" + QString::number(n+1) + "/";
            QString strPath = "/home/kylin/test";
            QString strType = ".sh";
            stAppStat* stStat = new  stAppStat();
            stStat->strPath = strPath;
            stStat->strType = strType;
            stStat->nKeeping = 1;
            m_mapApps.insert(strPath,stStat);
        }
    }


}

void KeepliveManager::StartProcess(const QString &path)
{
    QMutexLocker locker(&m_mutex);
    for (QMap<QString, stAppStat*>::const_iterator it = m_mapApps.begin(); it != m_mapApps.end(); ++it)
    {
        QString strPath = it.key();
        stAppStat* stStat = it.value();
        if(path == strPath || path.isEmpty())
        {
            QString strPid ;
            bool _bRet = isProcessRunning(strPath,strPid);
            emit sendStatSignal(strPath,strPid);
            if(!_bRet)
            {
                stStat->nKeeping = 1;
                QProcess::startDetached(strPath + stStat->strType);
            }
            if(path == strPath)
            {
                return;
            }
        }
    }
}
void KeepliveManager::StopProcess(const QString &path)
{
    QMutexLocker locker(&m_mutex);
    for (QMap<QString, stAppStat*>::const_iterator it = m_mapApps.begin(); it != m_mapApps.end(); ++it)
    {
        QString strPath = it.key();
        stAppStat* stStat = it.value();
        if(path == strPath || path.isEmpty())
        {
            QString strPid ;
            bool _bRet = isProcessRunning(strPath,strPid);
            if(_bRet)
            {
                QString command = QString("kill -9 %1").arg(strPid);
                QProcess process;
                process.start(command);
                process.waitForFinished(-1); // Wait indefinitely for the process to finish
                stStat->nKeeping = 0;
                emit sendStatSignal(strPath,"");
            }
            if(path == strPath)
            {
                return;
            }
        }
    }
}
void KeepliveManager::Watch()
{
    qDebug()<< "Watch" ;
    while(bruning_)
    {
        QThread::sleep(5);
        if(!bkeeping_)
        {
            qDebug()<< "keeplive is stop" ;
            continue;
        }
        UpdateProcess();
    }
}
void KeepliveManager::Watchasyn()
{
    std::thread _wth([&](){
        this->Watch();
    });
    _wth.detach();

}

总结

上述示例适用于Linux系统,使用QProcess 命令行判断进程是否存在和杀进程,跨平台则修改这两个功能函数即可。

标签:WatchColumn,Qt,void,QTableWidget,保活,tableWidget,ui,QString,strPath
From: https://blog.csdn.net/qq_17319357/article/details/143206821

相关文章

  • qt5multimedia播放rtsp延迟高
    Qt5Multimedia在Liunux平台已实现对Gstreamer的支持,近期在RK3588平台,使用Qt5Multimedia播放RTSP流时,遇到延迟高问题(3s左右),查看API,Qt5Multimedia无法向Gstreamer传递参数。解决办法:重新编译qt5multimedia;修改qt5multimedia/src/gsttools/qgstreamerplayersession.cppGstE......
  • Qt/C++路径轨迹回放/回放每个点信号/回放结束信号/拿到移动的坐标点经纬度
    一、前言说明在使用百度地图的路书功能中,并没有提供移动的信号以及移动结束的信号,但是很多时候都期望拿到移动的哪里了以及移动结束的信号,以便做出对应的处理,比如结束后需要触发一些对应的操作。经过搜索发现很多人都有这个需求,需要在js文件中加上一点代码才行,也就是在start开始......
  • 【模板】FHQtreap
    mt19937rnd(time(0));structFHQtreap{ intlc[N],rc[N],val[N],key[N],siz[N],pool,root; intcreate(intx){ intp=++pool; val[p]=x; siz[p]=1; key[p]=rnd(); lc[p]=rc[p]=0; returnp; } voidupdate(intp){ if(!p)return; siz[p]=siz[lc[p]]+si......
  • Qt中使用线程之QRunnable
    1、自定义1个子类继承自QRunnable2、重写run方法,编写子线程的业务逻辑3、使用QThreadPool的全局方法来开启这个线程4、线程的回收不需要关注,由QThreadPool处理5、缺点:无法使用信号槽机制6、适合一些不需要和主线程通信的耗时的任务举例:窗口创建时开启1个耗时任务,打印ui......
  • 关于MQTT的调研
    MQTT也可以理解成是一种消息队列。但是区别其它的消息队列,MQTT主要是针对低带宽高延迟的环境设计的,所以比较适合一些物联网的设备使用。相对来说也会比较轻量一点。MQTT也针对物联网领域的安全方便做了一些设计。EMQX在EMQX(https://cloud.emqx.com/console/)注册了一个免费的服务......
  • QT离线三维地图插件
    ​QT三维离线地图插件是一款功能强大的离线三维地图插件,支持多图源切换、海量点绘制、星历外推、航迹仿真、模型加载、倾斜数据加载,能够实现真实感的卫星仿真及航迹平滑处理。此外,该插件设计为便于二次开发,允许开发者根据特定需求扩展和定制功能,满足多样化的应用场景。支持Windo......
  • 基于PyQt Python的深度学习图像处理界面开发(二)
         Python标准库更多的适合处理后台任务,唯一的图形库tkinter使用起来很不方便,所以后来出现了针对Python图形界面开发的扩展库,例如PyQt。    在介绍PyQt之前,必须先简单介绍一下Qt。Qt是一个C++可视化开发平台,是一个跨平台的C++图形用户界面应用程序框架(C++......
  • MQTTnet 4.3.7.1207 (最新版)使用体验,做成在线客服聊天功能,实现Cefsharp的物联的功能(如
    一、MQTTnet4.3.x版本客户端将客户端集成到cefsharp定制浏览器中,实现物联网功能网上很多代码是3.x版本代码,和4.x版本差异性较大,介绍较为简单或不系统二、部分代码说明初始化,初始化》连接服务端》发布上线信息(遗嘱)ConnectAsync等订阅主题:SubscribeAsync......
  • Qt学习笔记(二)Qt 信号与槽
    系列文章目录Qt开发笔记(一)Qt的基础知识及环境编译(泰山派)Qt学习笔记(二)Qt信号与槽文章目录系列文章目录@[TOC](文章目录)前言一、Qt信号与槽机制1.1什么是信号和槽1.1信号和槽的关联及断连二、编辑槽函数1.自动关联2.手动关联前言  在学习Qt的过程中,信......
  • 用PyQt5中的textline实现log的实时显示
    在PyQt5中使用QLineEdit(即QTextLine的实现类之一)来实现日志的实时显示是可行的,但可能不适合大规模、多行日志的输出,因为QLineEdit仅支持单行文本。若要显示多行日志,建议使用QTextEdit,它更适合日志实时显示。但如果你确实希望使用QLineEdit来实现简单的日志输出,可以通......