将 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();
}
我正在尝试将 "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();
}