Я хотел бы иметь возможность отменить выбор элементов в моем QTreeView, щелкнув часть QTreeView без каких-либо элементов, но, похоже, я не могу найти этого. Я бы перехватил клик, который не на элементе, но QTreeView не имеет сигнала clicked
, поэтому я не могу понять, как это сделать.
Можно ли отменить выбор в QTreeView, щелкнув элемент?
Ответ 1
Это на самом деле довольно просто (в PyQt):
class DeselectableTreeView(QtGui.QTreeView):
def mousePressEvent(self, event):
self.clearSelection()
QtGui.QTreeView.mousePressEvent(self, event)
Qt использует mousePressEvent
для испускания clicked
. Если вы очистите выделение перед отправкой события, тогда, если элемент будет нажат, он будет выбран, иначе ничего не будет выбран. Большое спасибо Патрису за то, что он помог мне с этим:)
Ответ 2
Основываясь на решении @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
Яссир
Ответ 3
ClearSelection не работает в моем случае. Я использую treeviews с режимом singleleselection. Вот что я закодировал:
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
Ответ 4
QTreeView
наследует от QAbstractView
(http://doc.qt.digia.com/4.6/qtreeview.html), который имеет clicked
. Проблема в том, что сигнал испускается только тогда, когда индекс действителен, поэтому вы не можете достичь того, что хотите с этим сигналом.
Попробуйте перехватить mousePressEvent
. В функции вы можете найти, где пользователь щелкнул и отменил выбор выбранного элемента, если это необходимо.
Ответ 5
Чтобы добавить к @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
.
Благодаря этому ответу: fooobar.com/questions/313857/...
Ответ 6
Вы можете попробовать установить для своего виджета другой режим выбора. Я не знаю, действительно ли кто-то из них покрывает то, что кажется вам нужным (один выбор, но не выбран).
Ответ 7
В ответе @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);
}
}