使用QtCreator为软件制作更高级的界面。 基本上有一组用于调整和输入的按钮,一个启动和停止作业 按钮,我的问题来自一个冻结显示的无限循环,所以我想出了使用fork(),以便循环必须与主程序竞争,而不是吃掉整个资源(没有多线程),但程序崩溃吐痰:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not
been called
[xcb] Aborting, sorry about that.
a.out: ../../src/xcb_io.c:274: poll_for_event: Assertion
`!xcb_xlib_threads_sequence_lost' failed.
呼叫循环的功能被称为' ON',' OFF'应该退出分叉过程。
//in button 'ON' func
ps = fork();
if(getpid() == ps)
{
while(1)
{
strcpy(word, charset(minlength, maxlength, N));
ui->pass->setText(word);//operation on the display
....SNIP
}
}
//In button 'OFF' func
if(getpid() == ps)
exit(0);
我真的想知道启动一段时间(1)的正确方法是什么,并且能够在不使用QT冻结窗口的情况下中断,退出或返回,谢谢。
答案 0 :(得分:1)
你可能在这里崩溃:
ui->pass->setText(word);//operation on the display
与Qt一样,您无法直接从非UI线程更改UI。仅来自信号和插槽机制。
不冻结UI的正确方法显然是在另一个线程中计算冗长的操作。
您可以通过多种方式实现这一目标:
一个是通过对QObject
类进行子类化来创建'工作对象'这将执行所有繁重的操作。只要需要对象,就可以创建新的QThread
对象。并使用QObject::moveToThread
方法将创建的对象移动到新线程。要控制您的工作对象,您应该从对象发送信号并通过信号槽机制调用它的插槽。如果你直接调用它们 - 它们将在调用者线程中执行(所以不要执行像worker-> startHeavyJob();在UI线程中执行的操作)。而是在UI中发出信号(发出sigStartHeavyStuff();)并将其连接到工作对象的插槽(slotDoHeavyStuff();)
如果你不想打扰这个(如果操作很小) - 您可以使用QApplication::processEvents()处理UI事件循环中的事件,同时进入无限循环。
另一种方法是使用QtConcurrentRun框架在管理自身的单独线程中运行函数。线程从线程池中获取并由Qt管理。这种方法看起来像你想要做的事情。虽然您仍然只能通过信号和插槽访问UI对象。
答案 1 :(得分:1)
我看到所提出的代码中存在一个导致冻结的大问题:当你处于循环中时,你永远不会让Qt处理任何事情。您需要允许Qt运行它的事件循环。最简单的方法是在循环中使用QApplication::processEvents()
。
由于几个原因,我也不是while(1)
循环的粉丝。第一个是它可以吃机器周期等待事情发生。我怀疑你真的需要尽可能快地运行代码,你可能会在你的循环中躲开一些。
另一个问题是很难爆发。一种更清洁的方法就是这样的
void MyClass::on_pushButton_ON_clicked()
{
MyClass::done = false; // this is a class attribute
while (!MyClass::done) {
QApplication::processEvents();
//...
}
}
void MyClass::on_pushButton_OFF_clicked()
{
MyClass::done = true;
}