Создание фильтра событий

Я пытаюсь включить ключ delete в своем древовидной структуре. Это то, что у меня есть до сих пор:

class delkeyFilter(QObject):
    delkeyPressed = pyqtSignal()

    def eventFilter(self,  obj,  event):
        if event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Delete:
                self.delkeyPressed.emit()
                print 'delkey pressed'
                return True
        return False

Я соединяю eventfilter следующим образом:

    filter = delkeyFilter(self.dataTreeView)
    self.dataTreeView.installEventFilter(filter)

Почему мне нужно передать self.dataTreeview при создании фильтра? Это не сработает без него.

Ответ 1

@balpha верна. Простой ответ заключается в том, что если вы не передаете родительский или иным образом убедитесь, что экземпляр filter имеет ссылку на живое, он будет собирать мусор.

PyQt использует SIP для привязки к реализации Qt С++. Из Документация SIP:

Когда экземпляр С++ завернут, создается соответствующий объект Python. Объект Python ведет себя так же, как и в случае сбора мусора, - это сбор мусора, когда его счетчик ссылок достигает нуля. Что же происходит с соответствующим экземпляром С++? Очевидным ответом может быть то, что вызывается деструктор экземпляров. Однако API-интерфейс библиотеки может сказать, что когда экземпляр передается определенной функции, библиотека принимает на себя ответственность за экземпляр, т.е. Ответственность за вызов экземпляра-деструктора передается из созданного модуля SIP в библиотеку.

Собственность экземпляра также может быть связана с другим экземпляром. Подразумевается, что принадлежащий ему экземпляр будет автоматически уничтожен, если экземпляр владельца будет уничтожен. SIP отслеживает эти отношения, чтобы гарантировать, что циклический сборщик мусора Pythons может обнаруживать и прерывать любые эталонные циклы между принадлежащими и принадлежащими им экземплярами. Ассоциация реализуется как экземпляр-владелец, ссылающийся на принадлежащий ему экземпляр.

Из сказанного следует, что если вы передадите объект Python объекту Qt, который будет владеть, все будет работать, даже если вы не гарантировали, что ссылка на конкретный объект была сохранена.

Итак, чтобы повторить то, что @balpha сказал в своем комментарии, здесь один способ обхода для случая, когда вы не хотите передавать объект конструктору:

self.filter = delkeyFilter()
self.dataTreeView.installEventFilter(self.filter)

Ответ 2

Обработка ключей уже внедрена в QAbstractItemView. Все, что вам нужно сделать, это подкласс treeview, а затем реализовать keyPressEvent.

class MyTreeView(QTreeView):

    delkeyPressed = pyqtSignal()

    def __init__(self):
        QTreeView.__init__(self)

    def keyPressEvent(self, event): #QKeyEvent
        if event.key() == Qt.Key_Delete:
            self.delkeyPressed.emit()
            print 'del key pressed'

        # pass the event up the chain or we will eat the event
        QTreeView.keyPressEvent(self, event)

`