2010-07-22 5 views
10

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

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 когда я создаю фильтр? Без него это не сработает.

+3

* Я думаю * (но не конечно, поэтому не отправляйте в качестве ответа), что сборщик мусора Python будет есть ваш фильтр, если у него нет родителя, потому что установка фильтра событий не создает ссылку (на стороне python вещей). Чтобы убедиться в этом, попробуйте сохранить ссылку на 'filter' вокруг (например, сказать' self.filter = ... '), но не передавать родителя. – balpha

ответ

10

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

PyQt использует SIP для привязки к реализации на C++ Qt. От SIP documentation:

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

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

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

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

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

Управление ключами уже введено в действие 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) 

`

Смежные вопросы