2010-07-22 16 views
10

Estoy tratando de habilitar la tecla de borrar en mi vista de árbol. Esto es lo que tengo hasta ahora:Creando un filtro de evento

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 

conecto el eventfilter así:

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

¿Por qué necesito para pasar self.dataTreeview al crear el filtro? No funciona sin eso.

+3

* think * (pero no seguro, por lo tanto, no publicar como respuesta) que el recolector de basura de Python se comerá su filtro si no tiene un padre, porque la instalación del filtro de evento no crea una referencia (en el lado python de las cosas). Para verificar esto, intente mantener una referencia al 'filtro' (por ejemplo, diciendo' self.filter = ... ') pero sin pasarle a un padre. – balpha

Respuesta

10

@balpha es correcta. La respuesta simple es que si no pasa a un padre o si no se asegura de que la instancia filter tiene una referencia en vivo, será basura recolectada.

PyQt usa SIP para enlazar a la implementación C++ de Qt. De SIP documentation:

Cuando se cierra una instancia de C++, se crea un objeto de Python correspondiente. El objeto Python se comporta como se esperaría con respecto a la recolección de basura: es basura recolectada cuando su recuento de referencia llega a cero. ¿Qué ocurre con la instancia de C++ correspondiente? La respuesta obvia podría ser que se llama al destructor de la instancia. Sin embargo, la API de la biblioteca puede decir que cuando la instancia pasa a una función particular, la biblioteca toma posesión de la instancia, es decir, la responsabilidad de llamar al destructor de la instancia se transfiere desde el módulo SIP generado a la biblioteca.

La propiedad de una instancia también puede asociarse con otra instancia. La consecuencia es que la instancia de propiedad se destruirá automáticamente si se destruye la instancia propietaria. SIP realiza un seguimiento de estas relaciones para garantizar que el recopilador de basura cíclico de Python pueda detectar y romper cualquier ciclo de referencia entre las instancias propietarias y propietarias. La asociación se implementa como la instancia propietaria tomando una referencia a la instancia propiedad.

Lo anterior implica que si se pasa un objeto de Python a un objeto de Qt que toma posesión, todo lo que también va a funcionar, a pesar de que no se ha garantizado que se mantiene una referencia al objeto específico.

Por lo tanto, a repetir lo @balpha dijo en su comentario, aquí está una solución para el caso cuando no se desea pasar de un objeto al constructor:

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

El manejo de la llave ya está implícito en QAbstractItemView. Todo lo que tiene que hacer es crear una subclase de treeview, luego implementar 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) 

`