为什么我的异步QProgressBar呈现黑色?

时间:2015-11-27 21:30:27

标签: qt

我希望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 ();

除了进度条呈现为黑色块之外,它基本上可以正常工作。为什么会这样?

1 个答案:

答案 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()函数启动!