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 代码调用。因此,由于QLinedit.paste()它不是虚拟的,因此您将不得不拦截通常会导致 Qt 在内部调用它的所有事件。

这将意味着重新实现QLineEdit.keyPressEvent,以便您可以捕获默认键绑定的快捷方式;还有QLineEdit.contextMenuEvent,以便您可以修改默认上下文菜单。而且,根据您要执行的操作,您可能还需要覆盖默认的拖放处理。(如果您不想使用子类,可以使用事件过滤器来监视所有相关事件)。

QClipboard类提供对系统剪贴板的访问,这将允许您在粘贴之前截取文本。每个应用程序都有一个剪贴板对象,可以通过QApplication.clipboard()或访问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 回答