2010-05-03 12 views

Respuesta

10

Esto es en realidad bastante simple (en PyQt):

class DeselectableTreeView(QtGui.QTreeView): 
    def mousePressEvent(self, event): 
     self.clearSelection() 
     QtGui.QTreeView.mousePressEvent(self, event) 

Qt utiliza mousePressEvent para emitir clicked. Si borra la selección antes de enviar el evento, entonces, si se hace clic en un elemento, se seleccionará, de lo contrario, no se seleccionará nada. Muchas gracias a Patrice por ayudarme con esto :)

7

QTreeView hereda de QAbstractView (http://doc.qt.digia.com/4.6/qtreeview.html) que tiene una señal clicked. El problema es que la señal se emite solo cuando el índice es válido, por lo que no puede lograr lo que quiere con esta señal.

Intente interceptar el mousePressEvent en su lugar. En la función, puede encontrar dónde ha hecho clic el usuario y deseleccionar el elemento seleccionado si es necesario.

+0

Gracias. ¡He agregado mi propia respuesta pero +1 porque me ayudaste a llegar! – Skilldrick

+0

De nada Skilldrick –

0

Puede intentar establecer un selection mode diferente para su artilugio. No sé si alguno de ellos cubre lo que parece que desea (selección única, pero no seleccionable).

+0

No pude ver nada allí que lograra lo que quería, pero gracias de todos modos. – Skilldrick

8

clearSelection no funciona en mi caso. Estoy usando treeviews con un modo de selección individual. Esto es lo que he codificado:

class DeselectableTreeView : public QTreeView 
{ 
public: 
    DeselectableTreeView(QWidget *parent) : QTreeView(parent) {} 
    virtual ~DeselectableTreeView() {} 

private: 
    virtual void mousePressEvent(QMouseEvent *event) 
    { 
     QModelIndex item = indexAt(event->pos()); 
     bool selected = selectionModel()->isSelected(item); 
     QTreeView::mousePressEvent(event); 
     if (selected) 
      selectionModel()->select(item, QItemSelectionModel::Deselect); 
    } 

}; 

Esto funciona realmente bien.

Eric

13

@ Sobre la base de la solución de Eric, y ya que sólo se anula la selección de si se ha seleccionado el elemento se hace clic, esto es lo que ocurrió. Esta solución también funciona cuando hace clic en el área en blanco de la QTreeView

#ifndef DESELECTABLETREEVIEW_H 
#define DESELECTABLETREEVIEW_H 
#include "QTreeView" 
#include "QMouseEvent" 
#include "QDebug" 
class DeselectableTreeView : public QTreeView 
{ 
public: 
    DeselectableTreeView(QWidget *parent) : QTreeView(parent) {} 
    virtual ~DeselectableTreeView() {} 

private: 
    virtual void mousePressEvent(QMouseEvent *event) 
    { 
     QModelIndex item = indexAt(event->pos()); 
     bool selected = selectionModel()->isSelected(indexAt(event->pos())); 
     QTreeView::mousePressEvent(event); 
     if ((item.row() == -1 && item.column() == -1) || selected) 
     { 
      clearSelection(); 
      const QModelIndex index; 
      selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select); 
     } 
    } 
}; 
#endif // DESELECTABLETREEVIEW_H 

Yassir

+2

+1 Esto era lo que estaba buscando. – aardvarkk

+0

'indexAt' podría ser bastante caro, podría usar' item' en lugar de la segunda llamada. 'item.isValid()' es probablemente una mejor opción que comparar fila y columna a '-1'. Además, parece cambiar la selección si hace clic en los elementos? –

1

Para añadir a la respuesta @Skilldrick 's, si es necesario aplicar esto a una visión que ya ha sido ejemplarizado porque usted está utilizando Qt Designer, puede hacer algo como esto:

import new 
def mousePressEvent(self, event): 
    self.clearSelection() 
    QtGui.QTableView.mousePressEvent(self, event) 
self.ui.tableView.mousePressEvent = new.instancemethod(mousePressEvent, self.ui.tableView, None) 

esto supone que su vista es self.ui.tableView.

Gracias a esta respuesta: https://stackoverflow.com/a/1647616/1300519

0

En la respuesta por @Skilldrick, corremos el riesgo de enviar eventos superfluos. Si un elemento ya está seleccionado y lo estamos haciendo clic de nuevo, estamos levantando eventos deseleccionados y seleccionados. Según otros oyentes en su aplicación, esto podría no ser lo que desea.

La solución de @ eric-maeker solo anula la selección de un elemento si lo hacemos clic de nuevo mientras ya está seleccionado. Estrictamente hablando, esta no es la respuesta a la pregunta original, que fue cómo deseleccionar el elemento seleccionado al hacer clic en en otro lugar.

@ yassir-ennazk se acerca, pero como señala @ adrian-maire, la solución no es óptima. event->pos() se evalúa dos veces. Además, el evento del mouse siempre se evalúa llamando al QTreeView::mousePressEvent.

Esta es la solución que he encontrado, basada en las otras respuestas mencionadas anteriormente. Si estamos haciendo clic en un punto donde está presente otro elemento de vista de árbol, el nuevo elemento se selecciona reenviando el evento al TreeView. Si no, estamos limpiando la selección.

Tenga en cuenta que esto también funciona con QTreeWidget s.

virtual void mousePressEvent(QMouseEvent* event) 
{ 
    QModelIndex item = indexAt(event->pos()); 

    if (item.isValid()) 
    { 
     QTreeView::mousePressEvent(event); 
    } 
    else 
    { 
     clearSelection(); 
     const QModelIndex index; 
     selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select); 
    } 
} 
+0

Lo único malo con la implementación predeterminada es que no borra la selección al hacer clic en un área en blanco de la vista. Así que simplemente verifique si el índice como pos es válido. Si no es así, llame a 'clearSelection()'. A continuación, llame incondicionalmente a la clase base 'mousePressEvent'. – ekhumoro

Cuestiones relacionadas