如何找到包含 QtVirtualKeyboard 的 window
How to find the window that contains the QtVirtualKeyboard
我在嵌入式设备上使用 qt 小部件时遇到虚拟键盘问题。键盘显示为全屏并与所有应用重叠。
在文章 中描述了如何解决这个问题。
总之,你需要找到带键盘的QQuickWindow,在这个window上调用setMask。那么键盘上方的区域就会透明
我在如何使用虚拟键盘找到 QQuickWindow 时遇到问题。我尝试使用
QApplication::allWidgets()
但是 window 不在这里。
您可以将 findChildren
与继承 QObject
的任何 class 一起使用,例如 QApplication
。例如在 main.cpp:
QApplication a(argc, argv);
QList<QQuickWindow *> wind = a.findChildren<QQuickWindow *>();
这将为您提供指向应用程序中所有 QQuickWindow
的指针列表。
要获得所有 windows 你可以使用 QGuiApplication::allWindows()
但这还不够,因为 QtVirtualKeyboard window 不一定在开始时创建,所以 QInputMethod 的 visibleChanged 信号必须使用。我没有使用 QQuickWindow 中的信息进行过滤,因为通常应用程序可能有其他信息,而是使用 window 所属的 class 的名称。
#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()
我为使用 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
我在嵌入式设备上使用 qt 小部件时遇到虚拟键盘问题。键盘显示为全屏并与所有应用重叠。
在文章
总之,你需要找到带键盘的QQuickWindow,在这个window上调用setMask。那么键盘上方的区域就会透明
我在如何使用虚拟键盘找到 QQuickWindow 时遇到问题。我尝试使用
QApplication::allWidgets()
但是 window 不在这里。
您可以将 findChildren
与继承 QObject
的任何 class 一起使用,例如 QApplication
。例如在 main.cpp:
QApplication a(argc, argv);
QList<QQuickWindow *> wind = a.findChildren<QQuickWindow *>();
这将为您提供指向应用程序中所有 QQuickWindow
的指针列表。
要获得所有 windows 你可以使用 QGuiApplication::allWindows()
但这还不够,因为 QtVirtualKeyboard window 不一定在开始时创建,所以 QInputMethod 的 visibleChanged 信号必须使用。我没有使用 QQuickWindow 中的信息进行过滤,因为通常应用程序可能有其他信息,而是使用 window 所属的 class 的名称。
#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()
我为使用 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