在拖动/调整窗口大小的同时在窗口上调用isActive()时,返回false。 (X11,Qt 5.4.0)

我在Linux上使用Qt 5.4.0(X11),我需要确定,如果我的窗口是活动的。 所以,我写了下面给出的示例代码。 如果在Windows上编译该代码,则只有在窗口不是真正活动的情况下才会在控制台中logging“false”。 但在Linux(X11)上,当我开始拖动或调整窗口大小时,它也会logging“false”。 为什么会发生这种情况,以及如何解决在Linux上? 我想知道,当我的窗口是非活动的,当它是活跃的,但被拖动/resize。

代码片段(C ++):

void MainWindow::changeEvent(QEvent *e) { if (e->type() == QEvent::ActivationChange) { if (this->isActiveWindow()) { std::cout << "True" << std::endl; } else { std::cout << "False" << std::endl; } } } 

相同的代码,在PyQt5上:

 import sys from PyQt5.QtCore import Qt, QEvent from PyQt5.QtWidgets import QWidget, QApplication class TransparentWidget(QWidget): def __init__(self): super(TransparentWidget, self).__init__() def changeEvent(self, e): if e.type() == QEvent.ActivationChange: print(self.isActiveWindow()) if __name__ == '__main__': app = QApplication(sys.argv) transparent_widget = TransparentWidget() transparent_widget.show() app.exec_() 

它可能会记录“错误”,因为在X上,您看到的窗口实际上是两个窗口:您在其中绘制内容的窗口和略微大一点的窗口,这是您的父窗口并包含边框。

原因是X11没有关闭/最大/最小按钮,标题栏,漂亮的渐变颜色,圆角边框等“装饰边框”的概念(原生X11窗口可以有一个边框,但只能作为纯色或纹理)。 这些控件由您的窗口管理器提供。 会发生什么情况是,如果你创建一个窗口,窗口管理器会创建一个额外的X11窗口,这个窗口比你的窗口稍大一些,并且把你的窗口作为一个子窗口放在这个新窗口上。 从此,两个窗口紧密相连:调整窗口大小将调整父窗口的大小,反之亦然。

这一切都由窗口管理器处理。 例如,如果要调整窗口大小并单击边框,则单击不会到达窗口,而是到达窗口管理器,然后窗口管理器将确定点击的位置,并决定如何处理它。 所以在那一刻,你自己的窗口不再活跃,这就解释了为什么isActiveWindow()返回false。

使用Microsoft Windows时,边框是窗口本身的一个组成部分,所以这就是为什么它保持“活动”的原因。

无论如何,要确定你的窗口是否是“活动的”,你应该使用QFocusEvent。 通过查看gotFocus()和lostFocus()值,您应该能够跟踪您的窗口是否处于活动状态。

活动窗口是当前接受键盘输入焦点的窗口,因此也是发送键盘事件的窗口。

在调整大小/移动操作期间,活动窗口不会注册键盘事件(不管它们是否实际发送)。 鉴于此,在这样的行动期间窗口是否仍然被认为是活跃的是有争议的。

Qt4和Qt5在处理这个问题上有所不同。 在任何平台上调整大小/移动时,Qt4都不报告窗口激活更改(或焦点更改)(尽管我只是在X11和Windows上进行实际测试)。 Qt5也是如此 – 除了X11。

在X11上,Qt5会在所有调整大小/移动操作的开始和结束时报告窗口激活更改(以及焦点更改)。 也就是说, isActiveWindow()在操作开始时返回False ,在结束时返回True (还发送相应的FocusIn/FocusOut事件,以及WindowActivate/WindowDeactivate事件等等)。

可以说,X11上的Qt5行为是唯一准确的行为。 但是,它与Qt5支持的其他平台不一致,所以从开发人员的角度来看,它必须被认为是越野车(或者至少是不方便的)。

虽然Qt4的行为可以说是不太准确的,但它在所支持的所有平台上至少是一致的(即开发人员期望从跨平台工具包中得到的东西)。

不幸的是,调整大小/移动事件只是窗口激活更改之后才开始,所以似乎没有任何明显的方式来滤除Qt5中不需要的激活事件。