我有一个名为generate_input_event
的函数。我正在尝试使用此功能来模拟QWebEngineView中的按键。
def generate_input_event(window_id, key_code, modifiers, low_level_data, x, y):
modifiers_flag = create_modifiers_flag(modifiers)
logging.info("generate input, window: {} code: {}, modifiers {}".format(
window_id, key_code, modifiers_flag))
event = QKeyEvent(QEvent.KeyPress, key_code, modifiers_flag)
event.artificial = True
event_window = window.get_window(window_id)
QCoreApplication.sendEvent(event_window.qtwindow, event)
每当我运行程序并突出显示QWebEngineView中的输入字段并调用generate_input_event
时,都希望它将在输入字段中键入该字母。
我还设置了一个事件过滤器,以捕获除我人工生成的按键以外的所有按键。
class EventFilter(QWidget):
def __init__(self, parent=None):
super(EventFilter, self).__init__(parent)
qApp.installEventFilter(self)
def eventFilter(self, obj, event):
if (event.type() == QEvent.KeyPress and hasattr(event, 'artificial')):
logging.info("artificial event")
return False. # send to widget
elif (event.type() == QEvent.KeyPress and not is_modifier(event.key())):
modifiers = create_modifiers_list(event.modifiers())
key_string = create_key_string(event)
key_code = event.key()
logging.info("send code: {} string: {} modifiers {}".format(
key_code, key_string, modifiers))
return True. # do not forward to widgets
return False
但是,当我实际运行代码时,这是我得到的以下输出:
INFO:root:send code: 65 string: a modifiers ['']
INFO:root:generate input, window: 1 code: 65, modifiers <PyQt5.QtCore.Qt.KeyboardModifiers object at 0x106a4ea58>
INFO:root:artificial event
输出看起来正确,但是QWebEngineView的输入字段实际上从未得到generate_input_event
人工生成的字母。
P.S。如果出于上下文原因希望查看整个文件/项目,请在此处查看此分支/文件:https://github.com/atlas-engineer/next/blob/generate_events/ports/pyqt-webengine/utility.py
答案 0 :(得分:3)
Qt Webengine使用RenderWidgetHostViewQtDelegateWidget进行渲染,它是在加载页面后创建的,因此您必须在load()或setHtml()之后访问它,以便窗口小部件必须发送这些事件。
下面的示例将显示一个QWebEngineView和一个QLineEdit,同时显示两个窗口,您在QLineEdit中键入的内容将显示在QWebEngineView中。
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class EventFilter(QtCore.QObject):
def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.KeyPress and hasattr(
event, "artificial"
):
print("event:", event.key(), event.text())
return False
return super().eventFilter(obj, event)
class ForwardKeyEvent(QtCore.QObject):
def __init__(self, sender, receiver, parent=None):
super(ForwardKeyEvent, self).__init__(parent)
self.m_sender = sender
self.m_receiver = receiver
self.m_sender.installEventFilter(self)
def eventFilter(self, obj, event):
if self.m_sender is obj and event.type() == QtCore.QEvent.KeyPress:
# self.m_receiver.setFocus()
new_event = QtGui.QKeyEvent(
QtCore.QEvent.KeyPress,
event.key(),
event.modifiers(),
event.text(),
)
new_event.artificial = True
QtCore.QCoreApplication.postEvent(self.m_receiver, new_event)
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ef = EventFilter()
app.installEventFilter(ef)
lineedit = QtWidgets.QLineEdit()
lineedit.show()
view = QtWebEngineWidgets.QWebEngineView()
view.resize(640, 480)
view.show()
view.load(QtCore.QUrl("https://www.google.com/"))
# RenderWidgetHostViewQtDelegateWidget is created after loading a page
# so you must access it after load() or setHtml().
render_widget = view.findChild(QtWidgets.QWidget)
print(render_widget.metaObject().className())
assert(render_widget)
fe = ForwardKeyEvent(lineedit, render_widget)
sys.exit(app.exec_())
答案 1 :(得分:1)
可以通过以下最小示例来演示发布和侦听QWebengineview事件的正确方法:
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
from PyQt5.QtCore import Qt
class ForwardKeyEvent(QtCore.QObject):
def __init__(self, sender, receiver, parent=None):
super(ForwardKeyEvent, self).__init__(parent)
self.m_sender = sender
self.m_receiver = receiver
self.m_sender.installEventFilter(self)
def eventFilter(self, obj, event):
if self.m_sender is obj and event.type() == QtCore.QEvent.KeyPress:
new_event = QtGui.QKeyEvent(
QtCore.QEvent.KeyPress,
65,
Qt.KeyboardModifiers(),
"a",
)
new_event.artificial = True
QtCore.QCoreApplication.postEvent(self.m_receiver.focusProxy(), new_event)
return True
return False
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
lineedit = QtWidgets.QLineEdit()
lineedit.show()
view = QtWebEngineWidgets.QWebEngineView()
view.resize(640, 480)
view.show()
view.load(QtCore.QUrl("https://www.google.com/"))
# RenderWidgetHostViewQtDelegateWidget is created after loading a page
# so you must access it after load() or setHtml().
fe = ForwardKeyEvent(lineedit, view)
sys.exit(app.exec_())