是否可以通过单击某个项目来取消在QTreeView中的选择?

问题描述:

我希望能够通过点击没有任何项目的QTreeView的一部分来取消选择我的QTreeView中的项目,但我似乎无法找到这样做。我会拦截不在某个项目上的点击,但QTreeView没有clicked信号,所以我无法解决如何做到这一点。是否可以通过单击某个项目来取消在QTreeView中的选择?

这实际上是(在PyQt的)很简单:

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

Qt使用mousePressEvent发出clicked。如果您在发送事件前清除了选择,那么如果点击了一个项目,它将被选中,否则将不会选择任何项目。非常感谢Patrice帮助我解决这个问题:)

QTreeView继承自QAbstractViewhttp://doc.qt.digia.com/4.6/qtreeview.html),其具有clicked信号。问题是仅当索引有效时才发出信号,因此无法达到您想要的信号。

尝试拦截mousePressEvent。在该功能中,您可以找到用户点击的位置,并根据需要取消选择所选项目。

+0

谢谢。我已经添加了我自己的答案,但+1,因为你帮助我到达那里! – Skilldrick 2010-05-04 20:53:17

+0

不客气Skilldrick – 2010-05-04 22:07:39

您可以尝试为您的小部件设置不同的selection mode。我不知道它们中的任何一个是否涵盖了你想要的内容(单选,但是不可取消)。

+0

我看不到任何能达到我想要的东西,但无论如何感谢。 – Skilldrick 2010-05-04 20:59:53

clearSelection在我的情况下不起作用。我使用单选模式的treeviews。这是我编码:

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

}; 

这工作真的很好。

埃里克

基于@ Eric的解决方案,并且因为它仅取消选择,如果选择了点击的项目,这里是我想出了。 该解决方案当您单击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 

亚瑟尔

+2

+1这就是我一直在寻找的。 – aardvarkk 2014-04-01 17:59:07

+0

'indexAt'可能相当昂贵,您可以使用'item'而不是第二次调用。 'item.isValid()'可能比比较行和列到'-1'更好。 另外,它似乎改变了选择,如果点击元素? – 2016-05-17 09:17:13

的空白区域还致力于增加@Skilldrick的回答,如果你需要这个适用于已经是一个视图实例化,因为你使用Qt设计,你可以做这样的事情:

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

这是假设你的看法是self.ui.tableView

多亏了这样的回答:https://stackoverflow.com/a/1647616/1300519

在由@Skilldrick答案,我们就可能发送多余的事件。如果一个项目已经被选中,并且我们再次点击它,我们正在提出取消选择和选定的事件。根据应用程序中的其他监听器,这可能不是您想要的。

@ eric-maeker的解决方案只有当我们再次点击它时才会取消选择一个项目。严格来说,这不是原始问题的答案,这是如何在其他地方点击时如何取消选择的项目。

@ yassir-ennazk变得亲密了,但正如@adrian-maire指出的那样,这个解决方案并不是最优的。 event->pos()被评估两次。另外,总是通过调用QTreeView::mousePressEvent来评估鼠标事件。

下面是我提出的解决方案,基于上面提到的其他答案。如果我们点击另一个树形视图项目,则通过将事件转发到TreeView来选择新项目。如果不是,我们正在清除选择。

请注意,这也适用于QTreeWidget

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

默认实现唯一出错的地方是它在点击视图的空白区域时不会清除选择。所以只要检查索引是否为有效。如果不是,请调用'clearSelection()'。然后无条件地调用基类“mousePressEvent”。 – ekhumoro 2017-01-15 17:59:23