简体   繁体   English

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

[英]When calling isActive() on window while dragging/resizing it, false returns. (X11, Qt 5.4.0)

I'm using Qt 5.4.0 on linux (X11) and I need to determine, if my window is active. 我在Linux(X11)上使用Qt 5.4.0,我需要确定,如果我的窗口是活动的。 So, I wrote example code, given below. 所以,我编写了示例代码,如下所示。 If that code compiled on windows, it logs "false" in console only when window isn't really active. 如果该代码在Windows上编译,则仅当窗口未真正激活时,它才会在控制台中记录“false”。 But on linux (X11), it also logs "false" when I start to drag or resize window. 但是在linux(X11)上,当我开始拖动或调整窗口大小时,它也会记录“false”。 Why this happen and how to fix that on linux? 为什么会发生这种情况以及如何解决这个问题? I want to know, when my window is really inactive, and when it's active, but being dragged/resized. 我想知道,当我的窗口真的处于非活动状态时,它处于活动状态,但被拖动/调整大小。

code snippet (C++): code snippet(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;
        }
    }
}

same code, on PyQt5: 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_()

It probably registers 'false' because on X the window you see is actually two windows: the window where you paint your contents and a slighly larger window, which is the parent window of yours and contains the border. 它可能会记录'false',因为在X上你看到的窗口实际上是两个窗口:你绘制内容的窗口和一个稍大的窗口,它是你的父窗口并包含边框。

The reason is that X11 doesn't have a concept of a "decorated border" with close/max/min buttons, titlebar, nice gradient colors, rounded borders etc. (native X11 windows can have a border, but only as a solid color or texture). 原因是X11没有“装饰边框”的概念,具有关闭/最大/最小按钮,标题栏,漂亮的渐变颜色,圆形边框等。(原生X11窗口可以有边框,但仅作为纯色或纹理)。 Those controls are provided by your window manager. 这些控件由您的窗口管理器提供。 What happens is that if you create a window, the window manager creates an extra X11 window which is slightly larger than yours and places your window as a child on this new window. 会发生的情况是,如果您创建一个窗口,窗口管理器会创建一个额外的X11窗口,该窗口比您的稍大,并将您的窗口作为子窗口放在这个新窗口上。 From then on, the two windows are intimately linked: resizing your window will resize the parent window and vice versa. 从那时起,两个窗口紧密相连:调整窗口大小将调整父窗口的大小,反之亦然。

This is all handled by the window manager. 这全部由窗口管理器处理。 For example, if you want to resize the window and click on the border, the click goes not to your window but to the window manager, which then determines where the click was and decides what to do with it. 例如,如果要调整窗口大小并单击边框,则单击不会转到窗口,而是转到窗口管理器,窗口管理器会确定单击的位置并决定如何处理。 So at that moment your own window is not active anymore, which explains why isActiveWindow() returns false. 所以在那一刻你自己的窗口不再活动了,这就解释了为什么isActiveWindow()返回false。

With Microsoft Windows the border is an integral part of the window itself, so that's why it remains 'active'. 使用Microsoft Windows,边框是窗口本身不可或缺的一部分,因此它仍然是“活跃”的原因。

Anyway, to find out if your window is 'active' or not, you should use the QFocusEvent. 无论如何,要确定您的窗口是否处于“活动”状态,您应该使用QFocusEvent。 By looking at the gotFocus() and lostFocus() values you should be able to track when you window is active or not. 通过查看gotFocus()和lostFocus()值,您应该能够跟踪窗口何时处于活动状态。

The active window is the window that currently accepts the keyboard input focus, and therefore is also the window to which keyboard events are sent. 活动窗口是当前接受键盘输入焦点的窗口,因此也是发送键盘事件的窗口。

During a resize/move operation, the active window does not register keyboard events (whether they are actually sent or not). 在调整大小/移动操作期间,活动窗口不会注册键盘事件(无论它们是否实际发送)。 Given this, it is arguable whether the window should still be regarded as active during such operations. 鉴于此,在这种操作过程中窗口是否仍应被视为活动是有争议的。

Qt4 and Qt5 differ in how they deal with this. Qt4和Qt5在处理这个方面有所不同。 Qt4 does not report window activation changes (or focus changes) during a resize/move on any platform (I only actually tested on X11 and Windows, though). 在任何平台上调整大小/移动期间,Qt4不会报告窗口激活更改(或焦点更改)(尽管我只在X11和Windows上进行了实际测试)。 The same is also true for Qt5 - except when it comes to X11. Qt5也是如此 - 除了X11。

On X11, Qt5 reports a window activation change (and a focus change) at the start and end of all resize/move operations. 在X11上,Qt5在所有调整大小/移动操作的开始和结束时报告窗口激活更改(以及焦点更改)。 That is, isActiveWindow() returns False when the operation starts and True when it ends (and the corresponding FocusIn/FocusOut events are also sent, as well as WindowActivate/WindowDeactivate events, and so forth). 也就是说, isActiveWindow()在操作开始时返回False ,在结束时返回True (并且还发送相应的FocusIn/FocusOut事件,以及WindowActivate/WindowDeactivate事件,等等)。

It could be argued that the Qt5 behaviour on X11 is the only one that is accurate. 可以说X11上的Qt5行为是唯一准确的行为。 However, it is inconsistent with the other platforms Qt5 supports, and so from a developer's point of view it must be considered buggy (or at the very least, inconvenient). 但是,它与Qt5支持的其他平台不一致,因此从开发人员的角度来看,它必须被认为是错误的(或者至少是不方便的)。

Although the behaviour on Qt4 is arguably less acccurate, it is at least consistent across all the platforms it supports (ie it is exactly what a developer would expect from a cross-platform toolkit). 尽管Qt4上的行为可以说不那么准确,但它在所支持的所有平台上至少是一致的(即它正是开发人员对跨平台工具包的期望)。

Unfortunately, the resize/move events only begin after the window activation changes, so there does not seem to be any obvious way to filter out the unwanted activation events in Qt5. 不幸的是,调整大小/移动事件仅窗口激活更改后才开始,因此似乎没有任何明显的方法来过滤掉Qt5中不需要的激活事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM