2

QWebPage でフォーカスの変更に対応できるようにする必要があります。私は microFocusChanged() シグナルを使用しましたが、ほとんど望ましい動作が得られましたが、とにかく、どの要素が選択されているかを知る方法がわかりません。ページ上の編集可能な要素がフォーカスを取得または失ったときに、いくつかのアクションを実行したいと考えています。

前もって感謝します

4

2 に答える 2

7

ページ内のHTMLイベントを処理するには、次のようにします。

  1. イベントを受信するためのコールバックスロットを備えたQObjectを作成します。専用のハンドラーオブジェクトか、QDialog/QMainWindowのような既存のオブジェクトである可能性があります。
  2. QWebFrame.addToJavaScriptWindowObject(name、object)を使用してJavaScriptアクセス用のQObjectを登録します。
  3. JavaScriptを記述して、登録済みのQObjectのコールバックスロットを呼び出すHTMLイベントハンドラーを追加します。

フォーカス変更ハンドラーを追加するJavaScriptは、すべてのテキスト要素をトラバースし、onfocusハンドラーとonblurハンドラーを追加する必要があります。さらに良いのは、documentElementに単一のハンドラーを追加し、イベントバブリングを使用することです。残念ながら、onblur広告のonfocusはバブルしません。幸いなことに、DOMFocusInおよびDOMFocusOutと呼ばれるバブリングの対応物があります。

これは、ページテキスト要素のフォーカスイン/アウトイベントをキャッチする完全な例です。2つのスロット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 ++で書き直すことがあります)。

于 2010-05-17T10:04:32.400 に答える
0

私は同じ問題を抱えていましたが、 Javascript を無効にした状態でも動作させたかったので、 Javascript を使いたくありませんでしたQWebSettings。私は基本的に2つのアプローチを考えることができます:

  • 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)
    
于 2014-04-24T06:29:27.680 に答える