15

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

4

8 回答 8

18

基于@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

亚西尔

于 2012-05-31T02:40:38.440 回答
12

这实际上非常简单(在 PyQt 中):

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

Qt 用于mousePressEvent发射clicked. 如果您在发送事件之前清除选择,那么如果单击一个项目,它将被选中,否则不会被选中。非常感谢帕特里斯帮助我解决这个问题:)

于 2010-05-04T20:59:12.420 回答
9

clearSelection 在我的情况下不起作用。我正在使用具有单选模式的树视图。这是我编码的内容:

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

};

这真的很好。

埃里克

于 2011-02-22T08:40:54.657 回答
7

QTreeView继承自QAbstractViewhttp://doc.qt.digia.com/4.6/qtreeview.html),它有一个clicked信号。问题是仅当索引有效时才会发出信号,因此您无法使用此信号实现您想要的效果。

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

于 2010-05-04T06:15:43.443 回答
2

在@Skilldrick 的回答中,我们冒着发送多余事件的风险。如果已经选择了一个项目,并且我们再次单击它,我们将引发取消选择和选择的事件。根据您应用程序中的其他侦听器,这可能不是您想要的。

@eric-maeker 的解决方案只有在我们再次单击它时才取消选择一个已被选中的项目。严格来说,这不是原始问题的答案,即如何在单击其他位置时取消选择所选项目。

@yassir-ennazk 接近了,但正如 @adrian-maire 所指出的,解决方案不是最优的。event->pos()被评估两次。此外,鼠标事件总是通过调用来评估QTreeView::mousePressEvent

这是我根据上面提到的其他答案提出的解决方案。如果我们单击存在另一个树视图项的点,则通过将事件转发到TreeView. 如果没有,我们将清除选择。

请注意,这也适用于QTreeWidgets。

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);
    }
}
于 2017-01-14T22:26:30.317 回答
1

要添加到@Skilldrick的答案,如果您需要将其应用于已经实例化的视图,因为您使用的是 Qt Designer,您可以执行以下操作:

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

于 2016-01-13T16:19:39.097 回答
0

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

于 2010-05-04T14:49:13.927 回答
0

由于这个问题是专门关于 PyQt 的,我想根据 Nick Pruehs 的回答和 ekhumoro 的评论添加这个,这是实现这一目标的最简单方法:

class TreeView(QTreeView):
    def __init__(self, *args, **kwds):
        QTreeView.__init__(self, *args, **kwds)

    def mousePressEvent(self, event):
        item = self.indexAt(event.pos())

        if not item.isValid():
            self.clearSelection()
            
        QTreeView.mousePressEvent(self, event)
于 2020-11-29T14:10:13.617 回答