Qt相当于GObject.idle_add()

时间:2015-05-04 13:20:23

标签: qt4 pyqt4

在Qt中是否有与Gtk GObject.idle_add()方法相同的内容?

  

gobject.idle_add()函数添加一个函数,只要没有更高优先级的事件挂起到默认主循环。

我的研究让我得到了一些QTimer诡计:

QtCore.QTimer().singleShot(0, self.my_method)

但它看起来有点hackish,而不是那么简单,这让我觉得它可能不是最好的选择。

是否有" Qter"解?或者我不应该首先这样做?

上下文

我的GUI具有作用于绘图参数的小部件。当单击/编辑小部件/任何内容时,我使用信号/插槽刷新绘图。小部件可能会影响其他几个小部件,从而在单个用户单击时级联触发多个刷新操作,因此我正在寻找一种方法来避免在不需要时多次刷新:只有最后一次刷新才有意义。

我尝试在处理此类事件时断开信号,然后在完成时将它们连接回来并手动调用"#34;。我也尝试使用一个标志来禁止刷新方法,这种方法或多或少是等效的。这两种方式似乎都没那么复杂。

我正在思考而不是将每个小部件连接到refresh(),我可以将它们连接到refresh_request()方法,该方法会引发一个"刷新请求"标志并设置0秒计时器以在空闲时执行refresh_if_needed()以刷新标志是否被引发。只会发生一次刷新,因为只有在事件处理完成后才会执行。只有在真正修改了至少一个小部件的数据时才会刷新。此外,GUI可能会让用户感觉更加流畅,因为事件的处理速度会更快。

修改

而不是refresh_request()提升"刷新请求"标志并添加一个计时器来处理空闲时的标志,我可以让refresh_if_needed()永久地看到主循环中的标志,在这种情况下refresh_request()只需要处理标志。

这会是更好的设计吗?不确定,但无论如何,我的问题可能是"如何在Qt的主循环中添加一些任务?"。这会占用所有CPU吗?我是否需要添加"手册",500毫秒左右,暂停refresh_if_needed()?在这种情况下,我想我可以在正常模式下使用QTimer启动它(不是singleShot),但这是"正常"方式是什么?

无论如何,我仍然对等同于idle_add感兴趣。我想到的一个用例是我几年前编写的Gtk GUI。按钮开始或停止线程中的声音。为了避免竞争条件,我在主循环(code on GitHub(1000 LoC文件,而非修剪示例)中启动和停止声音。)

1 个答案:

答案 0 :(得分:1)

与Qt中的g_idle_add()等效,可以通过为您的一个小部件实现自定义事件来实现,该事件可以通过覆盖接收者的event()方法来处理,如documentation for Qt 5和已在评论中指出。

Qt 5示例(所有这些都与Qt 4类似)将是:

// Initialize event type
int customType = QEvent::registerEventType();

// Handle
bool MyWidget::event(QEvent* event) {
    if (event->type() == (QEvent::Type) customType) {
        // TODO: Do whatever your idle callback would do

        // Optional: Post event again to self if this should be repeated
        //           implementing behaviour of returning TRUE from g_idle_add callback

        return true;
    }

    // Else default handler, may want to replace QWidget with actual base of "MyWidget"
    return QWidget::event(event);
}

// Emit (given this is of type MyWidget)
QApplication::postEvent(this, new QEvent((QEvent::Type) customType));

但是,如果目标是始终像在OP的问题中那样始终将对信号的处理推迟到主循环中,则有一个更简便的选择。连接插槽和信号时,请为Qt::QueuedConnection的{​​{1}}参数指定typehere中记录了不同的连接类型。