2010-05-03 7 views

Antwort

10

Das ist eigentlich ganz einfach (in PyQt):

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

Qt mousePressEventclicked zu emittieren, verwendet. Wenn Sie die Auswahl vor dem Senden des Ereignisses löschen, wird bei Auswahl eines Elements diese ausgewählt, andernfalls wird nichts ausgewählt. Vielen Dank an Patrice für die Hilfe mit diesem :)

7

QTreeView erbt von QAbstractView (http://doc.qt.digia.com/4.6/qtreeview.html), die ein Signal clicked hat. Das Problem ist, dass das Signal nur dann ausgegeben wird, wenn der Index gültig ist, so dass Sie mit diesem Signal nicht erreichen können, was Sie wollen.

Versuchen Sie stattdessen, die mousePressEvent abzufangen. In der Funktion können Sie feststellen, wo der Benutzer geklickt hat und das ausgewählte Element bei Bedarf abwählen.

+0

Danke. Ich habe meine eigene Antwort hinzugefügt, aber +1, weil du mir dabei geholfen hast! – Skilldrick

+0

Gern geschehen Skilldrick –

0

Sie könnten versuchen, eine andere selection mode für Ihr Widget zu setzen. Ich weiß nicht, ob einer von ihnen das deckt, was Sie wollen (einfache Auswahl, aber abwählbar).

+0

Ich konnte nichts darin sehen, das würde erreichen, was ich wollte, aber trotzdem danke. – Skilldrick

8

Die clearSelection funktioniert nicht in meinem Fall. Ich verwende Baumansichten mit einem einzigen Auswahlmodus. Hier ist, was ich codiert habe:

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); 
    } 

}; 

Das funktioniert wirklich gut.

Eric

13

Basierend auf @ Eric-Lösung und wie sie abgewählt nur, wenn das geklickt Element ausgewählt wurde, hier ist das, was ich kam mit. Diese Lösung funktioniert auch, wenn Sie den leeren Bereich des

QTreeView klicken
#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 Das war, was ich gesucht habe. – aardvarkk

+0

'indexAt' könnte ziemlich teuer sein, Sie könnten' item' anstelle des zweiten Anrufs verwenden. 'item.isValid()' ist wahrscheinlich eine bessere Wahl als den Vergleich von Zeile und Spalte mit '-1'. Auch scheint es, die Auswahl zu ändern, wenn Sie auf Elemente klicken? –

1

Hinzufügen zu @Skilldrick ‚s Antwort, wenn Sie diese auf eine Ansicht anwenden müssen, das bereits instanziiert, weil Sie Qt Designer verwenden, können Sie etwas tun:

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

Dies setzt voraus, dass Ihre Ansicht self.ui.tableView ist.

Dank dieser Antwort: https://stackoverflow.com/a/1647616/1300519

0

In der Antwort von @Skilldrick, riskieren wir das Senden überflüssig Ereignisse. Wenn ein Element bereits ausgewählt ist und wir erneut darauf klicken, heben wir ausgewählte und ausgewählte Ereignisse auf. Basierend auf anderen Listenern in Ihrer Anwendung ist dies möglicherweise nicht das, was Sie möchten.

Die Lösung von @ eric-maeker hebt nur dann eine Auswahl auf, wenn wir sie erneut anklicken, während sie bereits ausgewählt ist. Streng genommen ist dies nicht die Antwort auf die ursprüngliche Frage, wie man das ausgewählte Objekt abstößt, wenn man woanders anklickt.

@ yassir-ennazk kommt nahe, aber wie von @ adrian-maire aufgezeigt, ist die Lösung nicht optimal. event->pos() wird zweimal ausgewertet. Außerdem wird das Mausereignis immer durch Aufrufen von QTreeView::mousePressEvent ausgewertet.

Hier ist die Lösung, die ich mir ausgedacht habe, basierend auf den anderen oben genannten Antworten. Wenn Sie auf einen Punkt klicken, an dem ein anderer Strukturansicht-Eintrag vorhanden ist, wird der neue Eintrag ausgewählt, indem das Ereignis an die Adresse TreeView weitergeleitet wird. Wenn nicht, löschen wir die Auswahl.

Beachten Sie, dass dies auch für QTreeWidget s funktioniert.

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

Das einzige Problem mit der Standardimplementierung ist, dass die Auswahl nicht gelöscht wird, wenn auf einen leeren Bereich der Ansicht geklickt wird. Prüfen Sie also, ob der Index als pos gültig ist. Wenn nicht, rufen Sie 'clearSelection()' auf. Rufen Sie dann bedingungslos die Basisklasse 'mousePressEvent' auf. – ekhumoro

Verwandte Themen