簡體   English   中英

小部件失去焦點時如何截取

[英]How can I intercept when a widget loses its focus

我有一個QPlainTextEdit ,想在內容失去焦點時進行處理。 我已經看到我可以使用focusChanged事件或focusOutEvent虛擬函數來執行此操作。

我不知道如何使用新語法傳遞參數(即my_app.focusChanged.connect(my_handler) ,其中my_handler是本地定義的函數)。 因此,我嘗試使用虛函數。

由於使用QT Designer創建接口時,繼承QPlainTextEdit是一個大問題,因此我嘗試通過簡單地使用my_text_edit.focusOutEvent = my_handler覆蓋虛擬函數。 這確實攔截了我想要的消息,但是它顯然覆蓋了QPlainTextEdit一些內置功能,並且出現了偽影-即,文本編輯中的光標在失去焦點時不會消失。 我認為我應該以某種方式調用原始事件,而對我有用的是:

在我的__init__方法中,我有:

    self.original_handler = self.my_text_edit.focusOutEvent
    self.my_text_edit.focusOutEvent = self.my_handler

my_handler的定義是:

    def my_handler(self, event):
        self.original_handler(event)
        # my own handling follows...

我基本上是在復制我希望圖書館為我做的事情。 我覺得這太笨拙了,我可以看到它在維護期間如何在許多方面產生適得其反的效果。 誰能建議一個更整潔的方法嗎? 謝謝!

就我個人而言,我從來沒有使用覆蓋虛擬方法的猴子補丁樣式,但是保留原始行為的正確方法是直接調用基類方法,如下所示:

def my_handler(self, event):
    QtGui.QPlainTextEdit.focusOutEvent(self.my_text_edit, event)
    # my own handling follows...

我不明白為什么您不能使用focusChanged信號。 它的處理程序將只是:

def my_handler(self, old, new):
    if old is self.my_text_edit:
        print('focus out')
    elif new is self.my_text_edit:
        print('focus in')

但是,我自己的偏好是使用事件過濾器

class Window(QtGui.QMainWindow)
    def __init__(self):
        ...
        self.my_text_edit.installEventFilter(self)

    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.FocusOut and
            source is self.my_text_edit):
            print('eventFilter: focus out')
            # return true here to bypass default behaviour
        return super(Window, self).eventFilter(source, event)

這是一個更加靈活的解決方案,它提供了一種通用方法來處理通過Qt Designer導入的任何窗口小部件(或者實際上是您不想子類化的任何窗口小部件)的任何事件類型

還可以進行小部件升級 ,可以用自己的子類直接替換生成的ui模塊中的小部件。 然后,這將允許您通過繼承覆蓋任何虛擬方法,而不是通過猴子修補單個實例。 如果要從Qt Designer導入多個具有相同自定義功能的相同類型的小部件,則可以提供一種非常干凈的解決方案。

我在以下回答中找到了有關如何在PyQt中進行小部件升級的簡單說明: 在運行時替換QWidget對象

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM