Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在拖动/调整窗口大小时对其调用isActive()时,返回false。(X11,Qt 5.4.0)_C++_Linux_Qt_Pyqt_X11 - Fatal编程技术网

C++ 在拖动/调整窗口大小时对其调用isActive()时,返回false。(X11,Qt 5.4.0)

C++ 在拖动/调整窗口大小时对其调用isActive()时,返回false。(X11,Qt 5.4.0),c++,linux,qt,pyqt,x11,C++,Linux,Qt,Pyqt,X11,我在linux(X11)上使用Qt5.4.0,我需要确定我的窗口是否处于活动状态。因此,我编写了下面给出的示例代码。若那个些代码是在windows上编译的,那个么只有当窗口并没有真正处于活动状态时,它才会在控制台中记录“false”。但在linux(X11)上,当我开始拖动或调整窗口大小时,它也会记录“false”。为什么会发生这种情况,以及如何在linux上修复这种情况?我想知道,我的窗口何时真的处于非活动状态,何时处于活动状态,但被拖动/调整大小 代码段(C++): 它可能会注册为“fals

我在linux(X11)上使用Qt5.4.0,我需要确定我的窗口是否处于活动状态。因此,我编写了下面给出的示例代码。若那个些代码是在windows上编译的,那个么只有当窗口并没有真正处于活动状态时,它才会在控制台中记录“false”。但在linux(X11)上,当我开始拖动或调整窗口大小时,它也会记录“false”。为什么会发生这种情况,以及如何在linux上修复这种情况?我想知道,我的窗口何时真的处于非活动状态,何时处于活动状态,但被拖动/调整大小

代码段(C++):


它可能会注册为“false”,因为在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中不需要的激活事件。

确切的行为可能取决于您的WM。为什么您认为它需要修复?首先,我可以在多个虚拟机上复制它,比如KDE(Kwin)、Unity(Compiz)、XFCE。我想这种行为是不恰当的。接下来,在Windows和OSX上运行的程序正常工作,当我拖动或调整窗口大小时,表示窗口处于活动状态。Qt就是这样创建的:程序在不同平台上的行为是相同的,这就是为什么应该修复这个问题。我们的团队也在bugtracker中报告了这一点。似乎没有明显的解决办法,因为调整大小/移动事件总是发生在激活更改之后。@BOOtak。如果你能在你的问题中添加一个Qt bug报告的链接,那会很有帮助。所以这一定是Qt5的问题,因为我不能用Qt4.8复制它(我没有安装Qt5)。这很奇怪,因为
isActive()
应该只告诉您的窗口是否有焦点。这不在Qt的控制之下,它只是报告状态。无论如何,我仍然坚持我的观点,即无论Qt应该做什么或不应该做什么,您都在做错事。我同意X11平台上的Qt5行为是准确的,但我使用isActive()方法确定我的窗口是否为前台。所以或许,Qt开发人员应该添加一些其他方法,例如isForeground(),以实现此目的。我将通过调用本机X11API方法来查找前台窗口,并将其发布在这里。
void MainWindow::changeEvent(QEvent *e) {
    if (e->type() == QEvent::ActivationChange) {
        if (this->isActiveWindow()) {
            std::cout << "True" << std::endl;
        } else {
            std::cout << "False" << std::endl;
        }
    }
}
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_()