【问题标题】:Qt - top level widget with keyboard and mouse event transparency?Qt - 具有键盘和鼠标事件透明度的顶级小部件?
【发布时间】:2010-11-02 11:43:25
【问题描述】:

我希望应用的主窗口忽略鼠标和键盘事件,将它们传递给窗口管理器 Z 顺序中位于其下方的应用程序。

我知道如何让 child 小部件忽略键盘或鼠标事件,但是主窗口呢?

我正在尝试制作一个桌面小部件,它始终位于背景之上,并且对键盘和鼠标事件完全不可见。 (通过)

Qt::X11BypassWindowManagerHint 让我通过键盘(虽然遗憾的是 X11 特定,但现在还好),那么鼠标事件呢?

是否有一种与操作系统无关的方式对键盘事件透明?

编辑:

这里的关键词是透明度。

我不想鼠标和键盘事件,我想让窗口管理器知道我根本不想要它们。这些事件应该指向我在 zorder 下的任何应用程序。

例如,我希望能够单击小部件覆盖的桌面图标并与它们进行交互,就像小部件不存在一样。

【问题讨论】:

  • 不知道为什么有人反对这个......完全合理的问题。不幸的是我没有答案,但我很确定它就在那里,因为如果我没记错的话,KDE 在桌面上有这些类型的小部件,它基于 Qt。
  • 你找到 Linux 的解决方案了吗?

标签: qt event-handling desktop-application


【解决方案1】:

我找到了以下解决方案(在 Linux 上测试,根据@TheSHEEEP 也适用于 Windows):

setWindowFlags(windowFlags() | Qt::WindowTransparentForInput);

它已在最近的 qt 版本中添加(我没有找到什么时候) 见http://doc.qt.io/qt-5/qt.html

【讨论】:

  • 我刚刚遇到了 WindowTransparentForInput 的一个不起眼的副作用:如果您还尝试为窗口设置 WA_TranslucentBackground 标志,它将停止工作,而窗口的背景颜色变为纯色。因此,在 Qt 中,用户输入的透明度似乎破坏了视觉透明度。除非他们试图实现一个非矩形窗口,否则没有人会遇到这种情况。
【解决方案2】:

在 Windows 上你可以设置WS_EX_TRANSPARENT

要在 Qt 中执行此操作,请使用以下代码:

包括标题,

#if _WIN32
    #include <windows.h>
#endif

并将以下代码放入构造函数中。

#if _WIN32
    HWND hwnd = (HWND) winId();
    LONG styles = GetWindowLong(hwnd, GWL_EXSTYLE);
    SetWindowLong(hwnd, GWL_EXSTYLE, styles | WS_EX_TRANSPARENT);
#endif

【讨论】:

    【解决方案3】:

    也许你想要的是

    widget->setAttribute(Qt::WA_TransparentForMouseEvents)
    

    ?这就是 QRubberBand 用来让它的父级处理鼠标事件的方法。至于键盘事件,QWidget 不会得到任何键盘事件,除非它自己设置了一个 focusPolicy()。

    setFocusPolicy( Qt::NoFocus );
    

    因此应该处理键盘事件。

    【讨论】:

    • 好的,这正是我所说的我已经知道该怎么做。我不想要一个让“它的父级处理鼠标事件”的小部件......我希望整个 APPLICATION 忽略它们。我想要告诉窗口环境(X、WinXP 等)点击我的应用程序应该只传递给位于 Z 顺序下的另一个应用程序。在键盘上打字应该做同样的事情。这些解决方案只是将事件从子小部件传递给父小部件。我希望将事件从父小部件发送回窗口管理器,或者很可能根本就不会发送到应用程序。
    • 但是,此响应对于可能真正想做您所说的事情的人很有用。 (将东西传递给客户)。我确实尝试过,如果 Qt 框架实际上识别出您正在尝试忽略父级别的事件并尝试将它们发送回窗口管理器(或在窗口管理器中设置某种标志以绕过)...但正如预期的那样,它没有用。我的应用吃掉了这些事件。
    • 对,对不起。从那以后,我还尝试了 setMask(),它可以满足您的需求,但也可以剪辑可见性。我很确定没有办法做你想做的事,而不会退回到特定于操作系统的黑客。您是否在任何其他应用程序中找到了您想要的功能?
    【解决方案4】:

    也许我在这里遗漏了一些东西,但是您是否尝试过继承 QMainWindow 类并覆盖 QWidget::event() 方法以始终返回 false?如果您需要处理某些事件,也可以在此处添加该智能。

    这种技术应该允许您检查进入应用程序的事件并在需要时忽略它们,而不必使用事件过滤器吃掉它们。

    如果这不起作用,您可以尝试通过调用QCoreApplication::notify() 将事件重定向到桌面,并将事件传递给通过调用QApplication::desktop() 获得的桌面小部件。我不知道这是否可行,但似乎值得一试。

    【讨论】:

      【解决方案5】:

      我认为覆盖应该起作用:

      bool YourMainWindow::event( QEvent *event )
      {
         event ->accept();
         return true;
      }
      

      这是 QWidget 类文档中关于 event() 成员函数的部分内容:

      如果 事件被识别,否则它 返回假。如果识别事件 被接受(见 QEvent::accepted), 任何进一步的处理,例如事件 传播到父小部件 停止。

      【讨论】:

        【解决方案6】:

        使用 Qt 的 event filters:它们将允许您的应用程序吃掉您指定的任何事件(即键盘和鼠标事件),但仍会处理其他事件,例如绘制事件。

        bool FilterObject::eventFilter(QObject* object, QEvent* event)
        {
            QKeyEvent* pKeyEvent = qobject_cast<QKeyEvent*>(event);
            QMouseEvent* pMouseEvent = qobject_cast<QMouseEvent*>(event);
        
            if (pKeyEvent || pMouseEvent)
            {
                // eat all keyboard and mouse events
                return true;
            }
        
            return FilterObjectParent::eventFilter(object, event);
        }
        

        【讨论】:

          猜你喜欢
          • 2011-01-01
          • 2013-01-04
          • 1970-01-01
          • 2011-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多