1

我的主线程上有一个 QDialog,我有一些逻辑发生在一个单独的线程上。当逻辑开始时,会发出一个连接到对话框上的 show() 的信号。当逻辑结束时,会发出一个连接到对话框上的 hide() 的信号。当逻辑确实起作用时,对话框会正确显示/隐藏。如果逻辑“什么都不做”并且信号只是按顺序发出,则对话框并不总是正确显示/隐藏。

我的连接与此类似:

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget* parent = 0) :
        Ui(new Ui::MainWindowUi),
        Transferer(new DataTransferer()),
        TransferProgress(this),
        TransferThread()
    {
        Ui->setupUi();
        connect(&Transferer, SIGNAL(Begin()), &TransferProgress, SLOT(show()));
        connect(&Transferer, SIGNAL(End()), &TransferProgress, SLOT(hide()));

        Transferer.moveToThread(&TransferThread);
        TransferThread.start();

        Transferer.DoStuff(true);
    }

    virtual ~MainWindow()
    {
        TransferThread.quit();
        TransferThread.wait(1000);            

        delete Ui;
        Ui = NULL;
    }

private:
    Ui::MainWindowUi* Ui;
    DataTransferer Transferer;
    TransferProgressDialog TransferProgress;
    QThread TransferThread;
}

逻辑看起来类似于:

class DataTransferer : public QObject
{
    Q_OBJECT
public:
    DataTransferer(QObject *parent) : QObject(parent) {}
    virtual ~DataTransferer() {}

    void DoStuff(bool dontDoStuff)
    {
        emit Start();
        if (!dontDoStuff)
        {
            QThread::sleep(1);
        }
        emit End();
    }
}

当 DataTransferer 做事时,一切正常。当对话框快速连续显示和隐藏时,我大约每隔一次调用 DoStuff() 就会得到一个幽灵对话框。

我使用了 QThread::currentThreadId() 并验证了对话框和逻辑在不同的线程上运行。

在这种情况下,为什么我的对话框不能正确隐藏?我是否应该强制我的逻辑始终运行至少几百毫秒(该解决方案很糟糕)?有没有办法让我的对话框在尝试隐藏之前确保它已完全加载?我应该以不同的方式处理这些信号/插槽吗?

编辑:我目前已经辞职,只是在我发出信号显示()对话框后放置一个 QThread::sleep(1) 。我不喜欢这个解决方案,但似乎没有其他方法有效。sleep(1) 允许对话框在隐藏之前一直出现。我也能够让它与 QThread::msleep(10) 一起工作,但这仍然导致大约 6 次尝试中的 1 次出现幽灵对话框。

每当我调用 show() 或 hide() 时,我都尝试在对话框逻辑中使用成员 QMutex,但这不起作用。

我将所有跨线程连接更改为使用 Qt::BlockingQueuedConnection 和 Qt::QueuedConnection ,但都没有成功。

我尝试将插槽连接从对话框移动到设置连接的对象,然后直接调用插槽,但这也没有证明是成功的。

4

3 回答 3

1

我有同样的问题,显示对话框,当得到一些信号关闭它时,当时间小于 20 毫秒(这意味着快速隐藏对话框),它会留下一个幽灵对话框。

所以,我只是使用

QTimer::singleShot(50, this, [this](){
    hide(); //hide dialog
});

在关闭处理函数中。它似乎运作良好。

于 2019-09-04T08:55:50.787 回答
0

我的猜测是出现问题是因为“显示”和“隐藏”调用交错。要验证这一点,请使用信号量 - 锁定对象直到显示完成,然后在隐藏中等待它。另请查看此处投票最多的答案以获得另一种可能(也许更好)的解决方案:在 QObjects 之间跨不同线程连接信号/插槽

于 2013-08-03T21:52:23.960 回答
0

用于Qt::BlockingQueuedConnection将信号连接到插槽。确保主线程的事件循环没有被阻塞。此外,如果您的工作线程使用大量 cpu 时间 - 您可以调用QThread::yeldCurrentThread()call.

于 2013-08-04T09:17:35.977 回答