我需要能够对 QWebPage 中的焦点变化做出反应。我使用了 microFocusChanged() 信号,它给了我几乎理想的行为,但无论如何我不知道如何知道选择了哪个元素。当页面上的任何可编辑元素获得或失去焦点时,我想执行一些操作。
先感谢您
要处理页面中的任何 HTML 事件,请执行以下操作:
添加焦点更改处理程序的 JavaScript 应遍历所有文本元素并添加 onfocus 和 onblur 处理程序。更好的是向 documentElement 添加单个处理程序并使用事件冒泡。不幸的是,onblur ad onfocus 不会冒泡。幸运的是,它们有一个冒泡的对应物,称为 DOMFocusIn 和 DOMFocusOut。
这是捕获页面文本元素的焦点输入/输出事件的完整示例。它在主窗口上声明了两个插槽handleFocusIn
并handleFocusOut
从 JavaScript 调用,并将主窗口注册为一个名为 的全局 JavaScript 变量MainWindow
。然后运行 JavaScript 将 DOMFocusIn/DOMFocusOut 事件绑定到这些插槽(间接地,因为我们需要过滤掉非文本元素)。
import sip
sip.setapi("QString", 2)
sip.setapi("QVariant", 2)
from PyQt4 import QtCore, QtGui, QtWebKit
class MyDialog(QtGui.QMainWindow):
def __init__(self):
super(MyDialog, self).__init__()
self.setWindowTitle("QWebView JavaScript Events")
web_view = QtWebKit.QWebView(self)
web_view.setHtml("""
<html>
<body>
<input type="text" name="text1"/><br/>
<input type="text" name="text2"/><br/>
<input type="submit" value="OK"/>
</body>
</html>""")
self.setCentralWidget(web_view)
main_frame = web_view.page().mainFrame()
main_frame.addToJavaScriptWindowObject("MainWindow", self)
doc_element = main_frame.documentElement()
doc_element.evaluateJavaScript("""
function isTextElement(el) {
return el.tagName == "INPUT" && el.type == "text";
}
this.addEventListener("DOMFocusIn", function(e) {
if (isTextElement(e.target)) {
MainWindow.handleFocusIn(e.target.name);
}
}, false);
this.addEventListener("DOMFocusOut", function(e) {
if (isTextElement(e.target)) {
MainWindow.handleFocusOut(e.target.name);
}
}, false)
""")
self.resize(300, 150)
@QtCore.pyqtSlot(QtCore.QVariant)
def handleFocusIn(self, element_name):
QtGui.QMessageBox.information(
self, "HTML Event", "Focus In: " + element_name)
@QtCore.pyqtSlot(QtCore.QVariant)
def handleFocusOut(self, element_name):
QtGui.QMessageBox.information(
self, "HTML Event", "Focus Out: " + element_name)
app = QtGui.QApplication([])
dialog = MyDialog()
dialog.show()
app.exec_()
(如果你真的不知道 Python,我可能会用 C++ 重写)。
我遇到了同样的问题,但不想使用 Javascript,因为我希望它即使在 .js 中禁用 javascript 也能正常工作QWebSettings
。我基本上可以想到两种方法:
按照建议收听microFocusChanged
信号,然后执行以下操作:
frame = page.currentFrame()
elem = frame.findFirstElement('input:not([type=hidden]):focus textarea:focus')
if not elem.isNull():
logging.debug("Clicked editable element!")
这当然有一些开销,因为microFocusChanged
被多次发出,并且在许多情况下,不仅仅是在选择输入字段时(例如,在选择文本时)。
这样做可能也很有意义,loadFinished
因为元素可以自动聚焦。
我还没有对此进行测试,但打算尽快实施。
如果我们只关心鼠标点击,扩展mousePressEvent
并在hitTestContent
那里做:
def mousePressEvent(self, e):
pos = e.pos()
frame = self.page().frameAt(pos)
pos -= frame.geometry().topLeft()
hitresult = frame.hitTestContent(pos)
if hitresult.isContentEditable():
logging.debug("Clicked editable element!")
return super().mousePressEvent(e)