#c #c #qt #qt5
#c #c #qt #qt5
Вопрос:
я хочу обновлять значение метки каждую секунду из команды, поэтому пытался отобразить его через цикл while … однако пользовательский интерфейс не загружается и не работает…
любые предложения / помощь будут оценены…
ниже приведен тестовый код…
#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);
}
}
Комментарии:
1. Ваш код навсегда застрянет в конструкторе MainWindow. Вместо этого вы можете использовать QTimer.
Ответ №1:
- Вы всегда должны возвращать управление в цикл событий. Ваш
while
цикл сделает ваше приложение невосприимчивым. - Происходит утечка экземпляра процесса.
- По крайней мере, вы могли бы использовать
awk
его в полной мере :netstat -i | awk '/ens33/ { print $3; exit 0 }'
. Ваша командная строка в любом случае недопустима, поскольку'
она не является допустимой escape-последовательностью 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(amp;m_label);
startTimer();
connect(amp;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. вы правы. Я забыл, что в Qt дочерние элементы удаляются от своих родителей при уничтожении.
2. @IvanGrynko Это не имеет ничего общего с Qt, так работает C . Когда у вас есть
class C : public D { A a; B b; };
, запускаются следующие деструкторы по порядку:B::~B, A::~A, C::~C, D::~D
. Представьте теперь, чтоD
это aQObject
.3. Я шокирован тем, что этот ответ был отклонен дважды. Он не только четко объясняет проблемы, но и предоставляет полный рабочий пример.
4. @KubaOber, что меня больше всего расстраивает, так это то, что голосование без объяснения причин, безусловно, контрпродуктивно. Я хотел бы, чтобы принудительное понижение голосов было оправдано, но я думаю, этого никогда не произойдет.
5. @Merlin069 Было объяснение одному из отрицательных голосов. Это было неправильно и с тех пор было удалено. Отрицательный ответ не может быть удален, поскольку я тем временем не редактировал вопрос (и я не буду просто разбираться с отрицательным ответом, мне сейчас нечего добавить). Вопрос по-прежнему остается чистым 16 повторений, так что кого это волнует 🙂
Ответ №2:
Проблема 1. Ваш цикл бесконечен, потому что значение tmp
не изменяется внутри цикла.
Проблема 2. Вы блокируете поток пользовательского интерфейса. Самое простое решение — добавить
while( true ) {
...
QCoreApplication::processEvents();
if( droc->waitForFinished( 10 ) )
break;
}
внутри вашего цикла. Но это не «в стиле qt» и может привести к трудноопределимым ошибкам.
Лучшее решение — передать connect
QProcess::finished
сигнал в метод и прочитать там стандартный вывод.
ПРИМЕЧАНИЕ: золотое правило асинхронного программирования — никогда не блокируйте основной поток надолго.
Комментарии:
1. Это плохой совет.
processEvents
(иexec
) возвращаются в цикл событий и являются источником трудно отслеживаемых ошибок. Не используйте их.