简体   繁体   English

为什么gui线程在槽中调用QLabel控件的setText方法响应慢?

[英]Why does the gui thread respond slowly to calling the setText method of the QLabel control in a slot?

Problem问题

I am developing a program with QT.我正在用 QT 开发一个程序。 Recently I found that sometimes calling the repaint method of the QLabel control takes two or three seconds in a slot function when I emit a signal in a thread.最近我发现当我在线程中发出信号时,有时调用 QLabel 控件的 repaint 方法在插槽 function 中需要两三秒。 While sometimes it takes only about one millisecond.虽然有时只需要大约一毫秒。 There is a difference when I make it sleep for different seconds in the run function of the thread.当我让它在线程的运行 function 中休眠不同的秒数时会有所不同。 Here is my code:这是我的代码:

main.cpp主文件

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.h主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "testthread.h"
#include <QDateTime>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    TestThread *m_testThread;  //thread
private slots:
    void onTestSlot();
};

#endif // MAINWINDOW_H

mainwindow.cpp主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>

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

    m_testThread = new TestThread();
    connect(m_testThread, &TestThread::sigTest, this, &MainWindow::onTestSlot);
    m_testThread->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onTestSlot()
{
    ui->label_resultSimilarity->setText("test");
    qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss:zzz") << ":【MainWindow::onTestSlot】start repaint";
    ui->label_resultSimilarity->repaint();
    qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss:zzz") << ":【MainWindow::onTestSlot】end repaint";
}

testthread.h测试线程.h

#ifndef FACERECOGNIZETHREAD_H
#define FACERECOGNIZETHREAD_H
#include <QThread>
#include <QImage>
#include <QDebug>
#include <QMainWindow>

class TestThread: public QThread
{
    Q_OBJECT
public:
    TestThread();
protected:
    void run();

signals:
    void sigTest();
};

#endif // FACERECOGNIZETHREAD_H

testthread.cpp测试线程.cpp

#include "testthread.h"
#include <QApplication>

TestThread::TestThread()
{

}

void TestThread::run()
{
    //QThread::msleep(200);
    QThread::msleep(500);
    emit sigTest();
}

mainwindow.ui主窗口.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>817</width>
    <height>478</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QLabel" name="label_preview">
    <property name="geometry">
     <rect>
      <x>93</x>
      <y>9</y>
      <width>571</width>
      <height>401</height>
     </rect>
    </property>
    <property name="sizePolicy">
     <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
      <horstretch>0</horstretch>
      <verstretch>0</verstretch>
     </sizepolicy>
    </property>
    <property name="layoutDirection">
     <enum>Qt::LeftToRight</enum>
    </property>
    <property name="frameShape">
     <enum>QFrame::Box</enum>
    </property>
    <property name="text">
     <string/>
    </property>
    <property name="scaledContents">
     <bool>false</bool>
    </property>
   </widget>
   <widget class="QWidget" name="widget" native="true">
    <property name="geometry">
     <rect>
      <x>679</x>
      <y>10</y>
      <width>131</width>
      <height>381</height>
     </rect>
    </property>
    <widget class="QLabel" name="label_resultImage">
     <property name="geometry">
      <rect>
       <x>10</x>
       <y>20</y>
       <width>111</width>
       <height>151</height>
      </rect>
     </property>
     <property name="frameShape">
      <enum>QFrame::Box</enum>
     </property>
     <property name="text">
      <string/>
     </property>
    </widget>
    <widget class="QLabel" name="label_resultSimilarity">
     <property name="geometry">
      <rect>
       <x>20</x>
       <y>210</y>
       <width>91</width>
       <height>20</height>
      </rect>
     </property>
     <property name="text">
      <string/>
     </property>
    </widget>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>817</width>
     <height>23</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

Additional remarks附加说明

After I edit the run method in testthread.cpp and make it sleep for 500 miliseconds, I would get the following result after I exec the program:在我编辑testthread.cpp中的run方法并使其休眠500毫秒后,我将在执行程序后得到以下结果:

"2021-05-26 00:15:31:641" :【MainWindow::onTestSlot】start repaint
"2021-05-26 00:15:34:605" :【MainWindow::onTestSlot】end repaint

However, after I edit the run method in testthread.cpp again and make it sleep for 200 miliseconds, I would get the following result after I exec the program:但是,在我再次编辑testthread.cpp中的run方法并使其休眠200毫秒后,执行程序后会得到以下结果:

"2021-05-26 00:14:55:954" :【MainWindow::onTestSlot】start repaint
"2021-05-26 00:14:55:970" :【MainWindow::onTestSlot】end repaint

I donot know why the gui thread respond to the repaint so slow.我不知道为什么 gui 线程对重绘的响应如此缓慢。 Is there any solutions to make it respond quickly?有什么解决方案可以让它快速响应吗? Thanks for any assistance.感谢您的任何帮助。

If you want ui updated immediatly,could change connection mode to 'Qt::BlockingQueueConnection'.And does the 'repaint()' calling is necessary after 'setData' method?如果您想立即更新 ui,可以将连接模式更改为“Qt::BlockingQueueConnection”。在“setData”方法之后是否需要调用“repaint()”? Good Luck~祝你好运~

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM