窗口系统如何通知QApplication?

Posted

技术标签:

【中文标题】窗口系统如何通知QApplication?【英文标题】:How is QApplication notified by the window system? 【发布时间】:2013-02-18 06:16:37 【问题描述】:

我开始使用 C++ 学习 Qt,并试图弄清楚事件机制是如何工作的。我有点了解它是如何在应用程序本身中工作的,以及 QApplication 如何处理事件并将它们排队以处理和通知对象/小部件。

不过,我还有一些悬而未决的问题:

    QApplication 本身如何通过窗口系统通知事件? 窗口系统如何知道我的小部件的内部命名,以便它可以告诉 QApplication 小部件“x”被点击、聚焦等。 如果窗口系统不知道小部件名称或没有对被点击小部件(或任何其他类型的事件)的引用,QApplication 如何确定需要通知哪个小部件。

提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

在 X11 上,Qt 轮询 xlib (Qt4) 或 XCB (Qt5) 的事件。使用 xlib,这将是 XNextEvent() 函数和其他相关函数:

http://www.x.org/archive/X11R7.5/doc/man/man3/XMaskEvent.3.html

如果您通过 grep 查找“XNextEvent”的 Qt 源代码,您可以找到使用它的地方。例如,在 Qt 4.8.4 源代码中:

$ grep -r XNextEvent 工具/qvfb/x11keyfaker.cpp: XNextEvent(dpy, &event); src/plugins/platforms/xlib/qxlibscreen.cpp: XNextEvent(mDisplay->nativeDisplay(), &event); src/gui/kernel/qwidget_x11.cpp: XNextEvent(X11->display, &ev); src/gui/kernel/qguieventdispatcher_glib.cpp: XNextEvent(X11->display, &event); src/gui/kernel/qeventdispatcher_x11.cpp: XNextEvent(X11->display, &event); src/gui/kernel/qapplication_x11.cpp: XNextEvent(X11->display, &nextEvent);

对于 XCB,有 xcb_wait_for_event()。

一旦 Qt 有了事件,它就可以开始通过小部件层次结构和 QML 分派它。

这当然只适用于 X11(即 Unix 和 Linux)。其他平台有不同的方式将事件传递给应用程序。

【讨论】:

【参考方案2】:

例如,在 windows 中,QWidget 只是一个带有 hwnd 和所有其他相关内容的普通窗口。 您甚至可以通过调用 EffectiveWinId() 方法来获取 hwnd。它使用标准的 Windows 消息循环来获取有关所有 Windows 事件的通知,您可以通过 QCoreApplication::setEventFilter 安装适当的过滤器来获得通知。 但是 Qt 也有 QML 部分和其他非本地的东西,为了让它工作,它使用了一些内部簿记,这取决于“外星小部件”的性质

上述所有对于非外星小部件都是正确的,外星小部件有些不同。 Alien widgets 由 Qt 本身管理,它是一个 Qt 工作来识别应该传播什么 QWidget 动作以及动作是什么。 Qt 从 4.4 开始默认使用外星小部件,但如果需要,它们可以很容易地被外星化。

其他操作系统在实现上有所不同,但思路是一样的。

【讨论】:

除了查看 Qt 的源代码之外,您还可以使用一些外部工具,如 Spy(在 Windows 上)来查看 Qt 应用程序中的内容。 这是相当古老的信息。由于 Qt 4.4 小部件不再是原生 Windows 窗口。 Roku 你有证据吗?一个链接也许?我认为情况正好相反。 @Roku,尝试在 Windows Qt 应用程序上使用 spy,你会看到 QWidgets 都是带有句柄的窗口。除了 Qt 的某些部分(例如打开\保存对话框)之外,我没有看到任何默认外星小部件的证据 所有 Qt 工具(Assistant、Createor 等)都基于外星小部件。所以我会更新我的答案

以上是关于窗口系统如何通知QApplication?的主要内容,如果未能解决你的问题,请参考以下文章

Qt窗口屏幕居中显示以及设置大小

必须在 QWidget Pyqt5 之前构造 QApp

QT:如何退出应用程序并关闭 UI

如何将一个 qApplication 的 GUI 嵌入到另一个 qApplication 的主窗口中?

vnpy源码阅读学习:学习vnpy的界面的实现

vnpy源码阅读学习学习vnpy的界面的实现