将 while(1) 循环中的文本插入到 QT 中的文本编辑器

Insert text in while(1) loop to texteditor in QT

我正在尝试将 "Some text" 打印到 QTextBrowser,持续 "n" 时间。其中 "n" 是整数。为此,我使用 QTimer::SingleShot 进行计时。一旦超时被触发,一个 FLAG 被设置为 false 并且这个 "FLAG" 在 while 循环中被监视以在 FLAG 为 false 时中断并且它应该插入文本直到 FLAG 被设置为 FALSE。 FLAG 的初始值为真。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    FLAG = true;

}

void MainWindow::on_pushButton_clicked()
{
    ui->pushButton->setEnabled(false);
   RunTheTimer();
    int counter = 0;

    do
    {
        ui->textBrowser->insertPlainText(QString("Inside While loop %1 \n").arg(counter++));
        counter++;
    }while(FLAG);

    FLAG = true;

}
void MainWindow::RunTheTimer()
{
     ui->textBrowser-> insertPlainText("Timer Started");
    QTimer::singleShot(60000, this, SLOT(Update()));// One Minute

}

void MainWindow::Update()
{
   ui->textBrowser-> insertPlainText("Timeout signal triggered");
    ui->pushButton->setEnabled(true);
   FLAG = false;
}
MainWindow::~MainWindow()
{
    delete ui;
}

当我单击按钮时,应用程序挂起。 调试后我观察到,一旦执行进入 while(1) 循环并且应用程序无法在 while(1) 循环中插入任何文本,超时就不会触发。为什么会有这种行为?我做错了什么?

谢谢。

您没有将控制权返回给事件循环,Qt 中的很多东西都无法在没有事件循环的情况下工作,看看 this page from the Qt wiki,在您的情况下:

  • QTextBrowser 将无法显示新添加的文本,因为这需要小部件能够接收绘制事件(如果没有事件循环,这是不可能的)。
  • 将您的标志设置为 false 的计时器将无法触发,因为您的程序总是忙于执行您的 while 循环,并且它将无法执行任何其他操作(除非它从 while 循环中退出,如果它不将你的标志设置为 false,这是不可能的。。。)。

如果你想尽可能重复地执行某件事,而不是使用无限循环,你可以使用QTimer并将其interval 属性设置为0,这是一个特殊值,一旦事件循环处理完事件队列中的所有事件,就会导致计时器超时。

使用上面的方法代替你的无限循环,你可以使用另一个定时器在特定时间后停止上面的定时器,你不必担心事件没有到达和定时器没有触发,因为事件循环现在总是在执行。

下面是上述方法的一个可能实现:

#include <QtWidgets>

int main(int argc, char* argv[]){
    QApplication a(argc, argv);

    //set up GUI
    QWidget widget;
    QVBoxLayout layout(&widget);
    QTextBrowser textBrowser;
    QPushButton button("Add Text");
    layout.addWidget(&textBrowser);
    layout.addWidget(&button);

    //timer with 0 interval instead of while loop
    QTimer workTimer;
    workTimer.setInterval(0);
    int counter=0;
    QObject::connect(&workTimer, &QTimer::timeout, [&]{
        //add text to textBrowser whenever the workTimer fires
        textBrowser.append(QStringLiteral("Additional Text %1").arg(counter++));
    });
    //when the button is clicked
    QObject::connect(&button, &QPushButton::clicked, [&]{
        //start work timer
        workTimer.start();
        button.setEnabled(false);
        //stop work timer after 5 seconds
        QTimer::singleShot(5000, [&]{
            workTimer.stop();
            button.setEnabled(true);
        });
    });
    widget.show();

    return a.exec();
}