【问题标题】:How to find the window that contains the QtVirtualKeyboard如何找到包含 QtVirtualKeyboard 的窗口
【发布时间】:2021-09-28 14:32:56
【问题描述】:

我在嵌入式设备上使用 qt 小部件,但虚拟键盘出现问题。键盘显示为全屏并覆盖所有应用程序。

在文章Virtual keyboard top black screen in Yocto 中描述了如何解决这个问题。

总之,你需要用键盘找到QQuickWindow,并在这个窗口上调用setMask。那么键盘上方的区域就是透明的

我遇到了如何使用虚拟键盘查找 QQuickWindow 的问题。我尝试使用

QApplication::allWidgets()

但窗口不在此处。

【问题讨论】:

  • 您好 - 您可以在此处包含该文章的相关部分吗?网址会发生变化,文章内容也会发生变化,因此我们希望确保所有问题都能经受住时间的考验 :)
  • 问题已编辑。感谢您的帮助。

标签: c++ qt qtvirtualkeyboard


【解决方案1】:

你可以使用QGuiApplication::allWindows()来获取所有的窗口,但这还不够,因为QtVirtualKeyboard窗口不一定是在开始时创建的,所以必须使用QInputMethod的visibleChanged信号。我没有使用来自 QQuickWindow 的信息进行过滤,因为通常应用程序可能有其他信息,而是使用窗口所属类的名称。

#include <QApplication>
#include <QWindow>
#include <cstring>

static void handleVisibleChanged(){
    if (!QGuiApplication::inputMethod()->isVisible())
        return;
    for(QWindow * w: QGuiApplication::allWindows()){
        if(std::strcmp(w->metaObject()->className(), "QtVirtualKeyboard::InputView") == 0){
            if(QObject *keyboard = w->findChild<QObject *>("keyboard")){
                QRect r = w->geometry();
                r.moveTop(keyboard->property("y").toDouble());
                w->setMask(r);
                return;
            }
        }
    }
}

int main(int argc, char *argv[])
{
    qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
    QApplication a(argc, argv);
    QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::visibleChanged, &handleVisibleChanged);
    // ...

Python 版本:

import os
import sys

from PySide2 import QtCore, QtGui, QtWidgets
# from PyQt5 import QtCore, QtGui, QtWidgets


def handleVisibleChanged():
    if not QtGui.QGuiApplication.inputMethod().isVisible():
        return
    for w in QtGui.QGuiApplication.allWindows():
        if w.metaObject().className() == "QtVirtualKeyboard::InputView":
            keyboard = w.findChild(QtCore.QObject, "keyboard")
            if keyboard is not None:
                r = w.geometry()
                r.moveTop(keyboard.property("y"))
                w.setMask(QtGui.QRegion(r))
                return


def main():
    os.environ["QT_IM_MODULE"] = "qtvirtualkeyboard"
    app = QtWidgets.QApplication(sys.argv)

    QtGui.QGuiApplication.inputMethod().visibleChanged.connect(handleVisibleChanged)

    w = QtWidgets.QLineEdit()
    w.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

【讨论】:

    【解决方案2】:

    您可以将findChildren 与任何继承QObject 的类一起使用,例如QApplication。例如在 ma​​in.cpp 中:

    QApplication a(argc, argv);
    QList<QQuickWindow *> wind = a.findChildren<QQuickWindow *>();
    

    这将为您提供指向应用程序中所有QQuickWindow 的指针列表。

    【讨论】:

      【解决方案3】:

      我为使用 Raspberry 和 PyQt5 的人提供了一个解决方案。 补完eyllanesc的回答,因为Python版本不支持PyQt5,其实我们有这个问题:

      TypeError: setMask(self, QRegion): argument 1 has unexpected type 'QRect'

      解决它:

      def handleVisibleChanged():
          if not QtGui.QGuiApplication.inputMethod().isVisible():
              return
          for w in QtGui.QGuiApplication.allWindows():
              if w.metaObject().className() == "QtVirtualKeyboard::InputView":
                  keyboard = w.findChild(QtCore.QObject, "keyboard")
                  if keyboard is not None:
                      region = w.mask()
                      rect = [w.geometry()]
                      rect[0].moveTop(keyboard.property("y"))
                      region.setRects(rect)
                      w.setMask(region)
                      return
      

      【讨论】:

      • 只更改w.setMask(QtGui.QRegion(r)),查看我的更新答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-23
      • 1970-01-01
      • 2012-05-16
      • 1970-01-01
      • 2017-02-24
      相关资源
      最近更新 更多