2

特定の編集ボックスの paste() をインターセプトしようとしています。多くの読書と頭を悩ませた後、大きなハンマーとモンキーパッチを試してみることにしました. これも私にはうまくいきませんでした。理由を知っている人はいますか?

import sys
from PyQt4 import QtGui

def myPaste():
  print("paste") # Never gets here

if __name__ == "__main__":
#    QtGui.QLineEdit.paste = myPaste # Try #1
    app = QtGui.QApplication(sys.argv)
    window = QtGui.QMainWindow()    
    window.setWindowTitle("monkey")
    centralWidget = QtGui.QWidget(window)

    edit = QtGui.QLineEdit(centralWidget)
#    QtGui.QLineEdit.paste = myPaste # Try #2
    edit.paste = myPaste # Try #3

    window.setCentralWidget(centralWidget)
    window.show()    
    app.exec_()

フィードバックに基づいて..イベントフィルターの提案を使用して問題を解決できました。更新されたサンプルコードは次のとおりです...

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = QtGui.QMainWindow()    
    window.setWindowTitle("monkey")

    centralWidget = QtGui.QWidget(window)
    edit = QtGui.QLineEdit(centralWidget)

    window.setCentralWidget(centralWidget)

    def eventFilter(obj, e):
        if isinstance(obj, QtGui.QLineEdit):
            if (e.type() == QtCore.QEvent.KeyPress):
                if (e.matches(QtGui.QKeySequence.Paste)):
                    obj.paste()
                    t=str(obj.text()).title() # Special handling here...uppercase each word for example
                    obj.setText(t)
                    return True
            return False
        else:
            return QtGui.QMainWindow.eventFilter(obj, e)

    window.eventFilter = eventFilter
    edit.installEventFilter(window)

    window.show()    
    app.exec_()
4

2 に答える 2

5

「モンキーパッチ」ができない理由QLineEdit.paste()は、それが仮想関数ではないからです。仮想関数に関する重要な点は、それらがオーバーライドされると、再実装された関数が Qt によって内部的に呼び出されることです。一方、非仮想オーバーライドは Python コードによってのみ呼び出されます。したがって、仮想ではないため、通常は Qt によって内部的に呼び出されるQLinedit.paste()すべてのイベントを傍受する必要があります。

これはQLineEdit.keyPressEventを再実装することを意味し、デフォルトのキー バインドのショートカットをトラップできるようにします。およびQLineEdit.contextMenuEventも使用できるため、デフォルトのコンテキスト メニューを変更できます。また、何をしようとしているのかによっては、デフォルトのドラッグ アンド ドロップ処理をオーバーライドする必要がある場合もあります。(サブクラスを使用したくない場合は、イベント フィルターを使用して関連するすべてのイベントを監視できます)。

QClipboardクラスはシステム クリップボードへのアクセスを提供します。これにより、テキストを貼り付ける前に傍受することができます。QApplication.clipboard()すべてのアプリケーションには、またはを介し​​てアクセスできるクリップボード オブジェクトが 1 つありますqApp.clipboard()

于 2012-12-04T20:41:42.220 に答える
3

QLineEdit必要なことを行うために、必要なカスタム貼り付け機能を提供するメソッドをサブクラス化して作成できます(pasteメソッドは仮想ではないため、オーバーライドされた場合、Qtコードから呼び出されません)。さらに、CTRL+Vのショートカットをインターセプトするためのイベントフィルターが必要になります。おそらく、クリップボードの内容を貼り付けるためにも使用されるマウスの中ボタンもフィルタリングする必要があります。pasteイベントフィルターから、メソッドの置換を呼び出すことができます。

次のコードを開始点として使用できます。

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class myEditor(QLineEdit):
    def __init__(self, parent=None):
        super(myEditor, self).__init__(parent)

    def myPaste(self):
        self.insert("custom text pasted! ")

class myWindow(QMainWindow):
    def __init__(self, parent=None):
        super(myWindow, self).__init__(parent)
        self.customEditor = myEditor(self)
        self.setCentralWidget(self.customEditor)
        self.customEditor.installEventFilter(self)

    def eventFilter(self, obj, e):
        if (obj == self.customEditor):
            if (e.type() == QEvent.KeyPress):
                if (e.matches(QKeySequence.Paste)):
                    self.customEditor.myPaste()
                    return True
            return False
        else:
            return QMainWindow.eventFilter(obj, e)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = myWindow()
    window.show()    
    app.exec_()

ここでのイベントフィルターは、貼り付け用のキーボードショートカットのみを処理します。私が言ったように、あなたはペースト操作の他のソースも考慮する必要があります。

于 2012-12-04T20:52:42.527 に答える