linux系统Qt实现简单任务管理器

在学习Qt实现简单的任务管理器的过程中学习了前辈的代码,原帖链接(https://blog.51cto.com/rangercyh/521262)。在测试过程中出现了点击系统信息后卡死的情况。
在原帖的评论区没看到相关问题的反馈,就自己看了一下代码。问题出在系统信息部分循环读取/proc/cpuinfo中信息的while (1)循环没有出口,死循环导致程序无响应。在各项信息都读取完之后加判断break就解决了。
本帖只简单地贴出代码,详见原帖。需要的ui文件在文章末尾,有需要自取。

main.cpp

//main.cpp
#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv); //应用程序类,每个应用程序有且只有一个
    MainWindow w; //实例化MainWindow类
    w.show(); //显示界面
    return a.exec(); //进入应用程序的循环中,直到程序退出
}

mainwindow.cpp

//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QFile>
#include <QMessageBox>
#include <QDir>
#include <QListWidget>
#include <QListWidgetItem>
#include <QStringList>
#include <QTimer>

int a0 = 0, a1 = 0, b0 = 0, b1 = 0;

MainWindow::MainWindow(QWidget *parent) : //构造函数,初始化ui,计时器
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    timer = new QTimer(this);
    QWidget::connect( timer, SIGNAL( timeout() ), this, SLOT( timer_update_currentTabInfo() ) );
    QWidget::connect( ui->tabWidget_INFO, SIGNAL( currentChanged() ),
                      this, SLOT( on_tabWidget_currentChanged() ) );
    timer->start(1000);
}

MainWindow::~MainWindow()
{
    delete ui;
    delete timer;
}

void MainWindow::timer_update_currentTabInfo()
{
    int index = ui->tabWidget_INFO->currentIndex();
    //定时器只刷新内存tab页面,用于进度条动态显示
    if (index == 0)
    {
        show_tabWidgetInfo(index);
    }
}

void MainWindow::show_tabWidgetInfo(int index)
{
    QString tempStr; //读取文件信息字符串
    QFile tempFile; //用于打开系统文件
    int pos; //读取文件的位置

    if (index == 0) //内存資源
    {
        tempFile.setFileName("/proc/meminfo"); //打开内存信息文件
        if ( !tempFile.open(QIODevice::ReadOnly) )
        {
            QMessageBox::warning(this, tr("warning"), tr("The meminfo file can not open!"), QMessageBox::Yes);
            return ;
        }
        QString memTotal;
        QString memFree;
        QString memUsed;
        QString swapTotal;
        QString swapFree;
        QString swapUsed;
        int nMemTotal, nMemFree, nMemUsed, nSwapTotal, nSwapFree, nSwapUsed;

        while (1)
        {
            tempStr = tempFile.readLine();
            pos = tempStr.indexOf("MemTotal");
            if (pos != -1)
            {
                memTotal = tempStr.mid(pos+10, tempStr.length()-13);
                memTotal = memTotal.trimmed();
                nMemTotal = memTotal.toInt()/1024;
            }
            else if (pos = tempStr.indexOf("MemFree"), pos != -1)
            {
                memFree = tempStr.mid(pos+9, tempStr.length()-12);
                memFree = memFree.trimmed();
                nMemFree = memFree.toInt()/1024;
            }
            else if (pos = tempStr.indexOf("SwapTotal"), pos != -1)
            {
                swapTotal = tempStr.mid(pos+11, tempStr.length()-14);
                swapTotal = swapTotal.trimmed();
                nSwapTotal = swapTotal.toInt()/1024;
            }
            else if (pos = tempStr.indexOf("SwapFree"), pos != -1)
            {
                swapFree = tempStr.mid(pos+10,tempStr.length()-13);
                swapFree = swapFree.trimmed();
                nSwapFree = swapFree.toInt()/1024;
                break;
            }
        }

        nMemUsed = nMemTotal - nMemFree;
        nSwapUsed = nSwapTotal - nSwapFree;

        memUsed = QString::number(nMemUsed, 10);
        swapUsed = QString::number(nSwapUsed, 10);
        memFree = QString::number(nMemFree, 10);
        memTotal = QString::number(nMemTotal, 10);
        swapFree = QString::number(nSwapFree, 10);
        swapTotal = QString::number(nSwapTotal, 10);

        ui->label_RAM_Used->setText(memUsed+" MB");
        ui->label_RAM_Left->setText(memFree+" MB");
        ui->label_RAM_Total->setText(memTotal+" MB");
        ui->label_SWAP_Used->setText(swapUsed+" MB");
        ui->label_SWAP_Left->setText(swapFree+" MB");
        ui->label_SWAP_Total->setText(swapTotal+" MB");

        ui->progressBar_RAM->setValue(nMemUsed*100/nMemTotal);
        ui->progressBar_SWAP->setValue(nSwapUsed*100/nSwapTotal);

        tempFile.close(); //关闭内存信息文件

        //wsj这段计算cpu使用率的方法有问题,使用另一篇中的方法:https://www.cnblogs.com/liushui-sky/p/9258101.html
        int tt = 2; //取2个点采样计算cpu当前利用律
        int cpuInfo[2][7];
        int cpuTotal[2][2];
        while (tt)
        {
            tempFile.setFileName("/proc/stat"); //打开CPU使用状态信息
            if ( !tempFile.open(QIODevice::ReadOnly) )
            {
                QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes);
                return;
            }
            tempStr = tempFile.readLine();
            for (int i = 0; i < 7; i++)
            {
                cpuInfo[2-tt][i] = tempStr.section(" ", i+1, i+1).toInt();
                cpuTotal[1][2-tt] += cpuInfo[2-tt][i];
                if (i == 3)
                {
                    cpuTotal[0][2-tt] += cpuInfo[2-tt][i];
                }
            }
            tt--;
            tempFile.close(); //关闭stat文件
        }

        int a = cpuTotal[0][1] - cpuTotal[0][0];
        int b = cpuTotal[1][1] - cpuTotal[1][0];
        if (a < 0)
        {
            a = -a;
        }
        if (b < 0)
        {
            b = -b;
        }
        ui->progressBar_CPU->setValue(a*100/b);

        tempFile.setFileName("/proc/stat");
        if ( !tempFile.open(QIODevice::ReadOnly) )
        {
            QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes);
            return;
        }

        tempStr = tempFile.readLine();
        a0 = a1;
        b0 = b1;
        a1 = b1 = 0;
        int gg;
        for (int i = 0; i < 7; i++)
        {
            b1 += tempStr.section(" ", i+2, i+2).toInt();
            gg = b1;
            if (i == 3)
            {
                a1 += tempStr.section(" ", i+2, i+2).toInt();
            }
        }
        int m, n;
        m = a1 - a0;
        n = b1 - b0;
        if (m < 0)
        {
            m = -m;
        }
        if (n < 0)
        {
            n = -n;
        }
        ui->progressBar_CPU->setValue( (n-m)*100/n );
        tempFile.close(); //关闭stat文件
    }

    else if (index == 1) //进程信息
    {
        ui->listWidget_process->clear();
        QDir qd("/proc");
        QStringList qsList = qd.entryList();
        QString qs = qsList.join("\n");
        QString id_of_pro;
        bool ok;
        int find_start = 3;
        int a, b;
        int nProPid; //进程PID
        int number_of_sleep = 0, number_of_run = 0, number_of_zombie = 0;
        int totalProNum = 0; //进程总数
        QString proName; //进程名
        QString proState; //进程状态
        QString proPri; //进程优先级
        QString proMem; //进程占用内存
        QListWidgetItem *title = new QListWidgetItem("PID\t" + QString::fromUtf8("名称") + "\t\t" +
                                                     QString::fromUtf8("状态") + "\t" +
                                                     QString::fromUtf8("优先级") + "\t" +
                                                     QString::fromUtf8("占用内存"), ui->listWidget_process);
        //循环读取进程
        while (1)
        {
            //获取进程PID
            a = qs.indexOf("\n", find_start);
            b = qs.indexOf("\n", a+1);
            find_start = b;
            id_of_pro = qs.mid(a+1, b-a-1);
            totalProNum++;
            nProPid = id_of_pro.toInt(&ok, 10);
            if(!ok)
            {
                break;
            }

            //打开PID所对应的进程状态文件
            tempFile.setFileName("/proc/" + id_of_pro + "/stat");
            if ( !tempFile.open(QIODevice::ReadOnly) )
            {
                QMessageBox::warning(this, tr("warning"), tr("The pid stat file can not open!"), QMessageBox::Yes);
                return;
            }
            tempStr = tempFile.readLine();
            if (tempStr.length() == 0)
            {
                break;
            }
            a = tempStr.indexOf("(");
            b = tempStr.indexOf(")");
            proName = tempStr.mid(a+1, b-a-1);
            proName.trimmed(); //删除两端的空格
            proState = tempStr.section(" ", 2, 2);
            proPri = tempStr.section(" ", 17, 17);
            proMem = tempStr.section(" ", 22, 22);

            switch ( proState.at(0).toLatin1() )
            {
                case 'S':   number_of_sleep++; break; //Sleep
                case 'R':   number_of_run++; break; //Running
                case 'Z':   number_of_zombie++; break; //Zombie
                default :   break;
            }

            if (proName.length() >= 12)
            {
                QListWidgetItem *item = new QListWidgetItem(id_of_pro + "\t" +
                                                            proName + "\t" +
                                                            proState + "\t" +
                                                            proPri + "\t" +
                                                            proMem, ui->listWidget_process);
            }
            else
            {
                QListWidgetItem *item = new QListWidgetItem(id_of_pro + "\t" +
                                                            proName + "\t\t" +
                                                            proState + "\t" +
                                                            proPri + "\t" +
                                                            proMem, ui->listWidget_process);
            }
        }
        QString temp;
        temp = QString::number(totalProNum, 10);
        ui->label_pNum->setText(temp);
        temp = QString::number(number_of_run, 10);
        ui->label_pRun->setText(temp);
        temp = QString::number(number_of_sleep, 10);
        ui->label_pSleep->setText(temp);
        temp = QString::number(number_of_zombie, 10);
        ui->label_pZombie->setText(temp);

        tempFile.close(); //关闭该PID进程的状态文件
    }

    else if (index == 2) //模块信息
    {
        ui->listWidget_model->clear();
        tempFile.setFileName("/proc/modules"); //打开模块信息文件
        if ( !tempFile.open(QIODevice::ReadOnly) )
        {
            QMessageBox::warning(this, tr("warning"), tr("The modules file can not open!"), QMessageBox::Yes);
            return ;
        }
        //设置模块首行项目
        QListWidgetItem *title = new QListWidgetItem( QString::fromUtf8("名称") + "\t\t\t" +
                                                      QString::fromUtf8("使用内存数") + "\t\t" +
                                                      QString::fromUtf8("使用次數"), ui->listWidget_model);

        QString mod_Name, mod_Mem, mod_Num;
        //循环读取文件内容,查找需要的信息
        while (1)
        {
            tempStr = tempFile.readLine();
            if (tempStr.length() == 0)
            {
                break;
            }
            mod_Name = tempStr.section(" ", 0, 0);
            mod_Mem = tempStr.section(" ", 1, 1);
            mod_Num = tempStr.section(" ", 2, 2);
            if (mod_Name.length() > 10)
            {
                QListWidgetItem *item = new QListWidgetItem(mod_Name + "\t\t" +
                                                            mod_Mem + "\t\t" +
                                                            mod_Num, ui->listWidget_model);
            }
            else
            {
                QListWidgetItem *item = new QListWidgetItem(mod_Name + "\t\t\t" +
                                                            mod_Mem + "\t\t" +
                                                            mod_Num, ui->listWidget_model);
            }
        }
        tempFile.close(); //关闭模块信息文件
    }

    else if (index == 3) //系统信息
    {
        int ok = 0;
        tempFile.setFileName("/proc/cpuinfo"); //打开CPU信息文件
        if ( !tempFile.open(QIODevice::ReadOnly) )
        {
            QMessageBox::warning(this, tr("warning"), tr("The cpuinfo file can not open!"), QMessageBox::Yes);
            return;
        }

        //循环读取文件内容,查找需要的信息
        while (1)
        {
            tempStr = tempFile.readLine();
            pos = tempStr.indexOf("model name");
            if (pos != -1)
            {
                pos += 13; //跳过前面的"model name:"所占用的字符
                QString *cpu_name = new QString( tempStr.mid(pos, tempStr.length()-13) );
                ui->label_CPUName->setText(*cpu_name);
                ok++;
            }
            else if (pos = tempStr.indexOf("vendor_id"), pos != -1)
            {
                pos += 12; //跳过前面的"vendor_id:"所占用的字符
                QString *cpu_type = new QString( tempStr.mid(pos, tempStr.length()-12) );
                ui->label_CPUType->setText(*cpu_type);
                ok++;
            }
            else if (pos = tempStr.indexOf("cpu MHz"), pos != -1)
            {
                pos += 11; //跳过前面的"cpu MHz:"所占用的字符
                QString *cpu_frq = new QString( tempStr.mid(pos, tempStr.length()-11) );
                double cpufrq = cpu_frq->toDouble(); //4核CPU
                cpu_frq->setNum(cpufrq*4);
                ui->label_CPUFrequency->setText(*cpu_frq + " HZ");
                ok++;
            }
            else if (pos = tempStr.indexOf("cache size"), pos!=-1)
            {
                pos += 13; //跳过前面的"cache size:"所占用的字符
                QString *cache_size = new QString( tempStr.mid(pos, tempStr.length()-16) );
                int cachesize = cache_size->toInt(); //4核CPU
                cache_size->setNum(cachesize*4);
                ui->label_CatheCapacity->setText(*cache_size + " KB");
                ok++;
            }
            else //跳过其他的内容
            {
            }
            if(ok == 4){break;}
        }
        tempFile.close(); //关闭CPU信息文件

        //打开操作系统信息文件
        tempFile.setFileName("/proc/version");
        if ( !tempFile.open(QIODevice::ReadOnly) )
        {
            QMessageBox::warning(this, tr("warning"), tr("The version file can not open!"), QMessageBox::Yes);
            return ;
        }
        tempStr = tempFile.readLine();
        pos = tempStr.indexOf("version");
        QString *os_version = new QString( tempStr.mid(0, pos-1) );
        ui->label_SystemType->setText(*os_version);

        int pos1 = tempStr.indexOf("(");
        QString *os_type = new QString( tempStr.mid(pos, pos1-pos-1) );
        ui->label_SystemVersion->setText(*os_type);

        pos = tempStr.indexOf("gcc version");
        pos1 = tempStr.indexOf("#");
        QString *gcc_info = new QString( tempStr.mid(pos+12, pos1-pos-14) );
        ui->label_GCCVersion->setText(*gcc_info);

        tempFile.close(); //关闭操作系统信息文件
    }

    else //说明
    {
    }
    return;
}

void MainWindow::on_pushButton_halt_clicked()
{
    system("halt");
}

void MainWindow::on_pushButton_reboot_clicked()
{
    system("reboot");
}


void MainWindow::on_tabWidget_INFO_currentChanged(int index)
{
    show_tabWidgetInfo(index); //显示tab中的内容
    return ;
}

void MainWindow::on_pushButton_pkill_clicked()
{
    //获得进程号
    QListWidgetItem *item = ui->listWidget_process->currentItem();
    QString pro = item->text();
    pro = pro.section("\t", 0, 0);
    system("kill " + pro.toLatin1());
    QMessageBox::warning(this, tr("kill"), QString::fromUtf8("该进程已被杀死!"), QMessageBox::Yes);
    //回到进程信息tab表
    show_tabWidgetInfo(1);
}

void MainWindow::on_pushButton_prefresh_clicked()
{
    show_tabWidgetInfo(1);
}

void MainWindow::on_pushButton_Model_install_clicked()
{
    show_tabWidgetInfo(2); //安装模块还不知道如何实现
}

void MainWindow::on_pushButton_Model_remove_clicked()
{
    show_tabWidgetInfo(2); //卸载模块还不知道如何实现
}

void MainWindow::on_pushButton_Model_refresh_clicked()
{
    show_tabWidgetInfo(2);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    Ui::MainWindow *ui; //界面资源类,所有的界面元素都是通过该类来调用
    QTimer *timer; //计时器

private slots:
    void on_pushButton_pkill_clicked();
    void on_pushButton_prefresh_clicked();
    void on_pushButton_Model_install_clicked();
    void on_pushButton_Model_remove_clicked();
    void on_pushButton_Model_refresh_clicked();
    void on_pushButton_reboot_clicked();
    void on_pushButton_halt_clicked();
    void on_tabWidget_INFO_currentChanged(int index);
    void timer_update_currentTabInfo();
    //显示tab中的内容
    void show_tabWidgetInfo(int index);
};

#endif // MAINWINDOW_H

如此一来就大功告成了。

免费下载本文所需ui文件

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux下,我们可以使用Qt来创建一个任务管理器Qt是一个跨平台的应用程序开发框架,可以帮助我们快速开发具有图形界面的应用程序。 首先,我们需要创建一个Qt应用程序,并设计一个主窗口来显示任务管理器的界面。在主窗口中,我们可以使用一个QTableWidget来显示当前运行的进程信息,包括进程ID,进程名称,内存使用情况等。 接着,我们可以使用Linux系统提供的一些工具来获取进程信息。例如,可以使用ps命令来获取所有进程的信息,并将其输出转换为字符串格式。然后,我们可以将这些信息解析为进程对象,并将其添加到QTableWidget中进行显示。 为了实现实时更新进程信息的功能,我们可以使用Qt的定时器来定时刷新进程列表。每次定时器触发时,我们都重新获取进程信息,并更新QTableWidget的显示内容。 除了显示进程信息,任务管理器还应该具备一些常见的操作,例如结束进程、显示进程的详细信息等。我们可以使用Linux提供的kill命令来结束进程,并使用Qt的QMessageBox来显示有关进程的详细信息。 最后,我们可以使用Qt的信号和槽机制来处理用户的交互操作。例如,当用户点击结束进程按钮时,我们可以发出一个信号,然后在槽函数中调用kill命令来结束选定的进程。 通过以上步骤,我们就可以实现一个简单Qt任务管理器。当用户打开应用程序时,它会自动获取并显示当前运行的进程信息。用户还可以通过界面上的按钮来结束选定的进程,以及查看进程的详细信息。这样,我们就可以在Linux下使用Qt创建一个功能强大的任务管理器

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值