Qt 每秒更新一次值
Posted
技术标签:
【中文标题】Qt 每秒更新一次值【英文标题】:Qt update value every second 【发布时间】:2014-06-26 16:35:20 【问题描述】:我想从命令中每隔一秒更新一次标签的值,所以一直在尝试通过 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);
【问题讨论】:
您的代码将永远停留在 MainWindow 构造函数中。您可以改用 QTimer。 【参考方案1】:-
您必须始终将控制权交还给事件循环。您的
while
循环将使您的应用程序无响应。
您正在泄漏流程实例。
至少您可以充分利用awk
:netstat -i | awk '/ens33/ print $3; exit 0 '
。无论如何,您的命令字符串都是无效的,因为 \'
不是有效的 C/C++ 转义序列。您无需转义单引号。
您无缘无故地调用了三个额外的进程(bash、grep 和 awk)。 Qt 完全能够提取您想要的数据。
您在堆上分配东西也没有充分的理由。请注意下面的代码中没有任何显式的new
和delete
。至少,您应该使用QScopedPointer
或std::unique_ptr
(但从不 std::auto_ptr
!)。
以下独立示例适用于 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"
【讨论】:
你是对的。我忘记了在 Qt 中,孩子们在销毁时会从他们的父母身上移除自己。 @IvanGrynko 这与 Qt 无关,它是 C++ 的工作原理。当您拥有class C : public D A a; B b; ;
时,以下析构函数按顺序运行:B::~B, A::~A, C::~C, D::~D
。现在想象D
是QObject
。
我很震惊这个答案被否决了两次。它不仅清楚地解释了问题,而且提供了一个完整的工作示例。
@KubaOber,最让我沮丧的是,在不解释原因的情况下投反对票肯定会适得其反。我希望看到强行投票是合理的,但我想这永远不会发生。
@Merlin069 对其中一个反对票进行了解释。这是错误的,已被删除。由于我同时没有编辑问题,因此无法删除不赞成票(而且我不会仅仅处理反对票,目前我没有太多要添加的内容)。问题仍然是净 16 代表,所以谁在乎 :)【参考方案2】:
问题 1. 你的循环是无限的,因为 tmp
的值在循环内没有改变。
问题 2。您阻塞了 UI 线程。最简单的解决方案是添加
while( true )
...
QCoreApplication::processEvents();
if( droc->waitForFinished( 10 ) )
break;
在你的循环中。但它不是“qt 风格”,可能会导致难以检测的错误。
最好的解决方案是connect
QProcess::finished
向一个方法发送信号并在那里读取标准输出。
注意:异步编程的黄金法则——永远不要长时间阻塞主线程。
【讨论】:
这是个坏建议。processEvents
(和exec
)递归到事件循环中并且是难以跟踪的错误的来源。不要使用它们。以上是关于Qt 每秒更新一次值的主要内容,如果未能解决你的问题,请参考以下文章