我希望QProgressBar在模式对话框中显示,并在另一个线程工作时异步更新。
struct ProgressThread : public QThread
{
QDialog m_dialog;
QProgressBar * m_bar;
ProgressThread (QWidget * parent, int range)
: m_dialog (parent)
, m_bar (new QProgressBar ())
{
auto l = new QGridLayout (& m_dialog);
l -> addWidget (m_bar, 0, 0);
m_bar -> setRange (0, range);
}
void run () override
{
m_dialog .exec ();
}
};
ProgressThread thread (this, range);
thread .start ();
int num = 0;
for (each job)
{
do_some_work ();
thread .m_bar -> setValue (++ num);
}
thread .m_dialog .accept ();
thread .wait (1000);
thread .quit ();
除了进度条呈现为黑色块之外,它基本上可以正常工作。为什么会这样?
答案 0 :(得分:1)
这是一个设计问题。尽管这种创新方法可能会发生,但Qt和大多数其他UI框架都没有设计为UI运行多个线程。大多数UI类只希望在同一主线程上运行。 Qt永远无法保证它的工作方式与您尝试的方式相同:在工作线程上运行对话框exec()。
如何将您拥有的源代码转换为Qt方式?您的源代码会立即在线程实例中封装QDialog和QProgressBar,这可能不会错误,直到您执行moveToThread(uiObject)。但是,它仍然显示错误的设计。您可以按照与UI交互的工作线程遵循正常模式:
// make sure to place it in the header file
class ProgressThread : public QDialog
{
Q_OBJECT
public:
// if you ever need to access that from outside
// QProgressBar* bar() {return m_bar;}
public slots:
void moveProgress(int);
private:
QProgressBar* m_bar;
};
class ProgressThread : public QThread
{
Q_OBJECT
public:
// add methods
signals:
moveProgress(int);
};
您需要将插槽连接到信号:
// for interthread communication a queued connection will be automatical
// figure out how to get the pointer to that dialog class (dialogPtr)
QObject::connect(&thread, SIGNAL(moveProgress(int)), dialogPtr(), SLOT(moveProgress(int));
从线程代码中发出信号以推进 UI线程上的进度条:
emit moveProgress(value);
类似的问题/答案:QProgressBar not showing progress?
并确保UI线程从应用程序main()函数启动!