Qt每秒更新一次

时间:2014-06-26 16:35:20

标签: c++ c qt qt5

我想从命令每隔一秒更新一个标签的值,所以一直尝试通过while循环显示它...但是UI没有加载而且不起作用...

任何建议/帮助将不胜感激......

下面是测试代码......

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

#include <QProcess>
#include <QString>
#include <QtCore/QTextStream>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QRegularExpressionValidator>

#include <iostream>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    txMessage();
}

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

void MainWindow::txMessage()
{
    QString command = "bash -c \"netstat -i | grep ens33 | awk \'{print $3}\'\"";
    int temp = 0;
    droc = new QProcess;
    while (temp != 1)
    {
        droc->start(command);
        droc->waitForFinished();
        QString value = droc->readAllStandardOutput();
        ui->label_3->setText(value);
    }
}

2 个答案:

答案 0 :(得分:0)

  1. 您必须始终将控制权返回给事件循环。您的while循环会使您的应用无响应。
  2. 您正在泄漏流程实例。
  3. 至少,您可以充分发挥awk的潜力:netstat -i | awk '/ens33/ { print $3; exit 0 }'。您的命令字符串无论如何都是无效的,因为\'不是有效的C / C ++转义序列。您无需转义单引号。
  4. 你无缘无故地调用了三个额外的进程(bash,grep和awk)。 Qt完全能够提取您想要的数据。
  5. 你也没有充分的理由在堆上分配东西。请注意,以下代码中没有明确的newdelete。至少,您应该使用QScopedPointerstd::unique_ptr(但从不 std::auto_ptr!)。
  6. 以下自包含示例适用于Qt 4和Qt 5。

    #include <QLabel>
    #include <QHBoxLayout>
    #include <QBasicTimer>
    #include <QProcess>
    #include <QApplication>
    
    class Widget : public QWidget {
        Q_OBJECT
        QHBoxLayout m_layout;
        QLabel m_label;
        QBasicTimer m_timer;
        QProcess m_process;
        void timerEvent(QTimerEvent * ev) {
            if (ev->timerId() == m_timer.timerId()) txMessage();
        }
        void txMessage() {
            m_timer.stop();
            m_process.start("netstat", QStringList() << "-i", QProcess::ReadOnly);
        }
        Q_SLOT void finished(int rc) {
            startTimer();
            if (rc != 0) {
                m_label.setText("Error");
            } else {
                QString output = QString::fromLocal8Bit(m_process.readAll());
                QStringList lines = output.split('\n', QString::SkipEmptyParts);
                foreach (QString line, lines) {
                    if (!line.contains("ens33")) continue;
                    QStringList args = line.split(' ', QString::SkipEmptyParts);
                    if (args.count() >= 3) {
                        m_label.setText(args.at(3));
                        return;
                    }
                }
            }
            m_label.setText("...");
        }
        void startTimer() {
    #if QT_VERSION>=QT_VERSION_CHECK(5,0,0)
            m_timer.start(1000, Qt::CoarseTimer, this);
    #else
            m_timer.start(1000, this);
    #endif
        }
    public:
        Widget(QWidget * parent = 0) : QWidget(parent), m_layout(this), m_label("...") {
            m_layout.addWidget(&m_label);
            startTimer();
            connect(&m_process, SIGNAL(finished(int)), SLOT(finished(int)));
        }
    };
    
    int main(int argc, char ** argv)
    {
        QApplication app(argc, argv);
        Widget w;
        w.show();
        return app.exec();
    }
    
    #include "main.moc"
    

答案 1 :(得分:-1)

问题1.你的循环是无限的,因为tmp的值在循环内没有改变。

问题2.您阻止了UI线程。最简单的解决方案是添加

while( true ) {
    ...
    QCoreApplication::processEvents();
    if( droc->waitForFinished( 10 ) )
        break;
}
循环中的

。但它不是&#q;风格&#39;并且可能导致难以发现的错误。

最佳解决方案是connect QProcess::finished向方法发出信号并在那里读取标准输出。

注意:异步编程的黄金法则 - 永远不会阻塞主线程。