Можно ли отменить выбор в QTreeView, нажав на элемент? - PullRequest
14 голосов
/ 04 мая 2010

Я хотел бы иметь возможность отменить выбор элементов в моем QTreeView, щелкнув часть QTreeView без элементов, но, похоже, я никак не могу это сделать. Я бы перехватил щелчок, который отсутствует на элементе, но QTreeView не имеет сигнала clicked, поэтому я не могу понять, как это сделать.

Ответы [ 7 ]

14 голосов
/ 31 мая 2012

Основано на решении @ 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

Ясир

10 голосов
/ 05 мая 2010

Это на самом деле довольно просто (в PyQt):

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

Qt использует mousePressEvent для излучения clicked. Если вы отмените выбор перед отправкой события, то при нажатии на элемент он будет выбран, иначе ничего не будет выбрано. Большое спасибо Патрису за помощь в этом:)

8 голосов
/ 22 февраля 2011

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

};

Это работает очень хорошо.

Eric

7 голосов
/ 04 мая 2010

QTreeView наследуется от QAbstractView (http://doc.qt.digia.com/4.6/qtreeview.html), который имеет сигнал clicked. Проблема в том, что сигнал излучается только тогда, когда индекс действителен, поэтому вы не можете достичь что вы хотите с этим сигналом.

Попробуйте вместо этого перехватить mousePressEvent. В функции вы можете найти, где пользователь щелкнул, и отменить выбор выбранного элемента.

1 голос
/ 15 января 2017

В ответе @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);
    }
}
1 голос
/ 13 января 2016

Чтобы добавить к ответу @ 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

0 голосов
/ 04 мая 2010

Вы можете попробовать установить другой режим выбора для вашего виджета. Я не знаю, охватывает ли какой-либо из них то, что вам нужно (одиночный выбор, но не выбираемый)

...