[英]How to capture key-press events when using QWebEngineView?
## minimal code
import sys
from PyQt5 import QtWidgets
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import Qt
class Browser(QWebEngineView):
def __init__(self, parent=None):
super(Browser, self).__init__(parent)
self.setHtml(r"""
<div><textarea></textarea></div>
<style>
*{margin:0;}
div {
height: 100%;
position: relative;
background:grey;
}
textarea {
background:red;
height: 50%;
width: 50%;
resize: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
""")
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
central=QtWidgets.QWidget(self)
self.setCentralWidget(central)
layout = QtWidgets.QGridLayout(central)
self.browser = Browser(central)
layout.addWidget(self.browser)
another=QtWidgets.QWidget(central)
layout.addWidget(another)
another.setFocusPolicy(Qt.StrongFocus)
def keyPressEvent(self, e):
print("KEY PRESSED")
return super().keyPressEvent(e)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.setGeometry(300, 50, 800, 600)
window.show()
sys.exit(app.exec_())
KEY PRESSED
登錄到控制台。KEY PRESSED
登錄到控制台。我希望所有案例都將KEY PRESSED
一次記錄到控制台中。
我嘗試向MainWindow
添加一個eventFilter
,但它給出了相同的輸出。
我還通過將關鍵事件轉發到MainWindow
嘗試了此答案的解決方案,但隨后它為案例 2 記錄了兩次KEY PRESSED
。
我無法區分傳播到MainWindow
的事件(案例 2)和未傳播的事件(案例 3),因此我可以實施一些措施來忽略多余的 function 調用。
問題是 Qt 必須將事件傳遞給內部 Chrome 瀏覽器,這使事件傳播的正常過程變得復雜。 我能找到的最簡單的解決方案是在內部 web-view 委托上安裝一個事件過濾器,同時忽略來自主按鍵處理程序中委托的任何事件:
from PyQt5.QtCore import QEvent
class Browser(QWebEngineView):
...
def eventFilter(self, source, event):
if event.type() == QEvent.KeyPress and source.parent() is self:
print("KEY PRESSED:", source)
return super().eventFilter(source, event)
def childEvent(self, event):
if event.added() and event.child().isWidgetType():
event.child().installEventFilter(self)
super().childEvent(event)
class MainWindow(QtWidgets.QMainWindow):
...
def keyPressEvent(self, e):
target = QtWidgets.QApplication.focusWidget()
if target.parentWidget() is not self.browser:
print("KEY PRESSED:", target)
return super().keyPressEvent(e)
我所做的是使用這篇文章中的ForwardKeyEvent
class 將關鍵事件從browser
轉發到MainWindow
。 我忽略了browser
發送的任何QKeyEvent
並接受了人為發送的 QKeyEvent。 這對我來說更方便,因為所有日志記錄都是由一個 function 完成的,這是在有 QKeyEvent 時需要調用的QKeyEvent
。
class ForwardKeyEvent(QObject):
## https://stackoverflow.com/a/57012924/14908508
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() == QEvent.KeyPress:
new_event = QKeyEvent(
QEvent.KeyPress,
event.key(),
event.modifiers(),
event.text(),
)
new_event.artificial = True
QCoreApplication.postEvent(self.m_receiver, new_event)
return super().eventFilter(obj, event)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
...
self.FKE = ForwardKeyEvent(self.browser.focusProxy(), self)
def keyPressEvent(self, e):
target = QtWidgets.QApplication.focusWidget()
if target.parentWidget() is not self.browser or hasattr(e,"artificial"):
print("KEY PRESSED:", target)
return super().keyPressEvent(e)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.