Qt 相当于 GObject.idle_add()
Qt equivalent to GObject.idle_add()
在 Qt 中是否有与 Gtk 的 GObject.idle_add()
方法等效的方法?
The gobject.idle_add()
function adds a function to be called whenever there are no higher priority events pending to the default main loop.
我的研究让我遇到了一些 QTimer
诡计:
QtCore.QTimer().singleShot(0, self.my_method)
但它看起来有点老套,不是那么简单,这让我觉得它可能不是最好的选择。
有"Qter"解决方案吗?或者我不应该首先这样做吗?
上下文
我的 GUI 具有根据绘图参数起作用的小部件。当小部件为 clicked/edited/whatever 时,我使用 signals/slots 刷新绘图。一个小部件可能会影响其他几个小部件,从而在一次用户单击时触发级联多个刷新操作,因此我正在寻找一种方法来避免在不需要时多次刷新:只有最后一次刷新才有意义。
我尝试在处理此类事件时断开信号,然后在完成后将它们连接回去并调用刷新 "manually"。我还尝试使用一个标志来抑制或多或少等效的刷新方法。这两种方式似乎都复杂得没用。
我在考虑不是将每个小部件连接到 refresh()
,而是将它们连接到 refresh_request()
方法,该方法会引发 "refresh request" 标志并将 0 秒计时器设置为如果标志被提升,空闲时执行 refresh_if_needed()
刷新。只会发生一次刷新,因为它只会在事件处理完成时执行。并且只有当至少一个小部件的数据确实被修改时它才会刷新。此外,GUI 可能会让用户感觉更流畅一些,因为事件的处理速度会更快。
编辑
与其让 refresh_request()
提升 "refresh request" 标志并添加一个计时器来处理空闲标志,不如让 refresh_if_needed()
从主循环中永久监视标志,在哪种情况 refresh_request()
只需要处理标志。
这样的设计会更好吗?不确定,但无论如何,我的问题可能是 "how can I add some task to the main loop in Qt?"。这会吃掉所有 CPU 吗?我是否需要添加一个 "manual",500 毫秒左右,在 refresh_if_needed()
中暂停?在这种情况下,我想我可以在正常模式下使用 QTimer
启动它(不是 singleShot),但这是 "normal" 方式吗?
无论如何,我仍然对 idle_add
的等价物感兴趣。我想到的一个用例是我几年前编写的 Gtk GUI。这些按钮启动或停止线程中的声音。为了避免竞争条件,我在主循环中开始和停止声音(code on GitHub(1000 LoC 文件,不是精简的示例))。
相当于 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 的问题一样,那么有一个更简单的选择。连接槽和信号时,为QObject::connect()
的type
参数指定Qt::QueuedConnection
。记录了不同的连接类型 here.
在 Qt 中是否有与 Gtk 的 GObject.idle_add()
方法等效的方法?
The
gobject.idle_add()
function adds a function to be called whenever there are no higher priority events pending to the default main loop.
我的研究让我遇到了一些 QTimer
诡计:
QtCore.QTimer().singleShot(0, self.my_method)
但它看起来有点老套,不是那么简单,这让我觉得它可能不是最好的选择。
有"Qter"解决方案吗?或者我不应该首先这样做吗?
上下文
我的 GUI 具有根据绘图参数起作用的小部件。当小部件为 clicked/edited/whatever 时,我使用 signals/slots 刷新绘图。一个小部件可能会影响其他几个小部件,从而在一次用户单击时触发级联多个刷新操作,因此我正在寻找一种方法来避免在不需要时多次刷新:只有最后一次刷新才有意义。
我尝试在处理此类事件时断开信号,然后在完成后将它们连接回去并调用刷新 "manually"。我还尝试使用一个标志来抑制或多或少等效的刷新方法。这两种方式似乎都复杂得没用。
我在考虑不是将每个小部件连接到 refresh()
,而是将它们连接到 refresh_request()
方法,该方法会引发 "refresh request" 标志并将 0 秒计时器设置为如果标志被提升,空闲时执行 refresh_if_needed()
刷新。只会发生一次刷新,因为它只会在事件处理完成时执行。并且只有当至少一个小部件的数据确实被修改时它才会刷新。此外,GUI 可能会让用户感觉更流畅一些,因为事件的处理速度会更快。
编辑
与其让 refresh_request()
提升 "refresh request" 标志并添加一个计时器来处理空闲标志,不如让 refresh_if_needed()
从主循环中永久监视标志,在哪种情况 refresh_request()
只需要处理标志。
这样的设计会更好吗?不确定,但无论如何,我的问题可能是 "how can I add some task to the main loop in Qt?"。这会吃掉所有 CPU 吗?我是否需要添加一个 "manual",500 毫秒左右,在 refresh_if_needed()
中暂停?在这种情况下,我想我可以在正常模式下使用 QTimer
启动它(不是 singleShot),但这是 "normal" 方式吗?
无论如何,我仍然对 idle_add
的等价物感兴趣。我想到的一个用例是我几年前编写的 Gtk GUI。这些按钮启动或停止线程中的声音。为了避免竞争条件,我在主循环中开始和停止声音(code on GitHub(1000 LoC 文件,不是精简的示例))。
相当于 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 的问题一样,那么有一个更简单的选择。连接槽和信号时,为QObject::connect()
的type
参数指定Qt::QueuedConnection
。记录了不同的连接类型 here.