Qt обновляет значение каждую секунду

#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:

  1. Вы всегда должны возвращать управление в цикл событий. Ваш while цикл сделает ваше приложение невосприимчивым.
  2. Происходит утечка экземпляра процесса.
  3. По крайней мере, вы могли бы использовать awk его в полной мере : netstat -i | awk '/ens33/ { print $3; exit 0 }' . Ваша командная строка в любом случае недопустима, поскольку ' она не является допустимой escape-последовательностью C / C . Вам не нужно экранировать одинарные кавычки.
  4. Вы вызываете три дополнительных процесса без всякой причины (bash, grep и awk). Qt вполне способен извлекать нужные вам данные.
  5. Вы также размещаете вещи в куче без уважительной причины. Обратите внимание на отсутствие каких-либо явных 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 это a QObject .

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 ) возвращаются в цикл событий и являются источником трудно отслеживаемых ошибок. Не используйте их.