2015-05-05 110 views
1

我的QLabel未从插槽更新。我使用QObject::moveToThread运行在独立的线程中发件人类:QLabel未从插槽调用更新

QThread* serviceThread = new QThread; 
service = new ExportService(); 
connect(service,SIGNAL(stateChanged(Service::ServiceState)), 
     this,SLOT(statusChanged(Service::ServiceState))); 
service->moveToThread(serviceThread); 
serviceThread->start(); 

服务对象由与ServiceState枚举值冒落信号发送状态时,该信号是由QDialog槽捕获:

void Dialog::statusChanged(Service::ServiceState s) 
{ 
    switch (s) { 
    case Service::IDLE: 
     qDebug() << "Idle"; 
     ui->label->setText("Service send response succesfully."); 
     break; 
    case Service::REQUESTING: 
     qDebug() << "Requesting"; 
     ui->label->setText("Requesting response from service..."); 
     break; 
    case Service::ERROR: 
     qDebug() << "Error"; 
     ui->label->setText("Error. Cannot get response from service."); 
     break; 
    default: 
     break; 
    } 
} 

在对象上操作之后其发出两次信号,第一次的值为Service::REQUESTING,第二次的值为Service::IDLE我的QLabel仅将文本更改为“服务发送响应成功”。在控制台中,我可以看到qDebug() << "Requesting";正常工作,所以状态更改成功。

评论出来后后ui->label->setText("Service send response succesfully.");标签已经变为请求国,但整个操作即完成我看到的“请求”,在控制台则“空闲”和QLabel更改后。

如果我想查看QLabel实时更改,该怎么办?

+1

“请求”状态有多长时间?也许它太快了?用户界面是否响应? –

+0

我想像@FrankOsterfeld一样。看起来'QLabel'更新速度太快,您无法修改更改。 –

+2

你还需要明确指定'Qt :: QueuedConnection'在你的'connect()'调用中移动到另一个线程的对象。 –

回答

2

首先,尝试setText()后加入update(),没准setText()不会自动调度repaint()QLabel,如果它工作,然后问题就解决了。


但是,update()功能:

http://doc.qt.io/qt-4.8/qwidget.html#update

无效了QWidget :: update()方法

此功能不会导致立即重绘;相反,当Qt返回到主要的 事件循环时, 会安排一个绘画事件进行处理。这允许Qt优化更多的速度和更少的 闪烁比调用repaint()

>调用update()几次通常会导致paintEvent()调用仅有一个 。

基本上说,如果你打电话给他们太频繁,他们中的一些将被优化掉。

如果这不是所需的行为,请尝试在setText()之后添加强制repaint(),或使用计时器安排周期性强制重绘。

http://doc.qt.io/qt-4.8/qwidget.html#repaint


UPDATE

正如在评论中提到,迫使repaint()没有很好的解决方案。

此答案旨在提供代码行为的原因分析,“强制repaint()”建议更多的是验证此分析的方法,而不是解决问题的方法。

但是,如果没有关于该计划目的的进一步信息,就很难提供进一步的建议。

+0

谢谢,它的工作原理!这种方法会产生不良后果吗? – Sajmplus

+1

我认为这个建议是不好的做法。如果状态需要第二次更改,那么只要依靠内置的update/repaint机制就足够了,除非其他内容阻塞了UI线程的绘制。如果速度非常快,用户不会看到状态改变 –

+0

@FrankOsterfeld我同意。强制'repaint()'可能会导致比解决问题更多的问题。我想真正的问题是,自动'repaint()'足够频繁的实际使用,如果不是那么如何改善? – user3528438

1

从请求到空闲的状态变化很快发生。文本“请求服务响应...”不在标签上,不足以让眼睛看到它。

事实上,“请求......”在调试输出证明了这一点,但是如果你想要更多的证据还有其他事情可以做:

  1. 使用计数每一个柜台调用statusChanged()函数并将其显示在与状态文本相同的标签上(除状态文本外)或不同的标签。

  2. 向调试输出端添加一个高精度定时器输出 - 查看状态变化有多近。

  3. 使用几个复选框,一个用于空闲状态,一个用于请求状态。在收到相应状态时更改其状态。即收到第一个空闲时,将复选框设置为选中状态。收到下一个空闲时,将其切换为未选中状态。

我只是接受调试输出告诉事实并继续前进。