【问题标题】:Why does my asynchronous QProgressBar render black?为什么我的异步 QProgressBar 呈现黑色?
【发布时间】:2015-11-30 11:39:21
【问题描述】:

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

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

【问题讨论】:

  • 如果我在主线程中执行(new QProgressBar ())->show();,它也会呈现黑色,并且仅在工作块完成后绘制。

标签: qt


【解决方案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() 函数开始!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多