Делаем только один столбец QTreeWidgetItem редактируемым - PullRequest
25 голосов
/ 10 мая 2010

У меня есть QTreeWidgetItem с двумя столбцами данных, есть ли способ сделать редактируемым только второй столбец? Когда я делаю следующее:

QTreeWidgetItem* item = new QTreeWidgetItem();
item->setFlags(item->flags() | Qt::ItemIsEditable);

все столбцы становятся редактируемыми.

Ответы [ 10 ]

27 голосов
/ 14 ноября 2012

Вы можете сделать только определенные столбцы в QTreeWidget редактируемыми, используя обходной путь:

1) Установите для свойства editTriggers QTreeWidget значение NoEditTriggers

2) При вставке элементов установите флаг Qt: ItemIsEditable объекта QTreeWidgetItem

3) Подключите следующий слот к сигналу "itemDoubleClicked" объекта QTreeWidget:

void MainWindow::onTreeWidgetItemDoubleClicked(QTreeWidgetItem * item, int column)
{
    if (isEditable(column)) {
        ui.treeWidget->editItem(item, column);
    }
}

где "isEditable" - это написанная вами функция, которая возвращает true для редактируемых столбцов и false для нередактируемых столбцов.

18 голосов
/ 11 января 2011

Недавно у меня была такая же проблема, и я нашел решение, которое работает со всеми EditTriggers, не только с DoubleClicked (и соединением с сигналом двойного щелчка)

Создать делегат, который возвращает нулевой указатель для редактора:

class NoEditDelegate: public QStyledItemDelegate {
    public:
      NoEditDelegate(QObject* parent=0): QStyledItemDelegate(parent) {}
      virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
        return 0;
      }
    };

И позже используйте его как пользовательский делегат для вашего столбца

ui->parameterView->setItemDelegateForColumn(0, new NoEditDelegate(this));
8 голосов
/ 01 декабря 2010

Похоже, что стандартный QTreeWidget не позволяет этого. Я думаю, что есть два способа сделать это:

  1. Используйте QTreeView со своим собственным классом, производным от QAbstractItemModel, и переопределите функцию flags

  2. Используйте QTreeView с QStandardItemModel. Затем, когда вы добавляете элемент, просто установите соответствующий столбец, чтобы разрешить редактирование:

Вот код для второго варианта:

QString x, y;
QList<QStandardItem*> newIt;
QStandardItem * item = new QStandardItem(x);
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
newIt.append(item);
item = new QStandardItem(y);
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEditable);
newIt.append(item);
model->appendRow(newIt);

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

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

Похоже, вам придется отказаться от использования QTreeWidget и QTreeWidgetItem и перейти с QTreeView и QAbstractItemModel. Классы Widget - это удобные классы, которые являются конкретными реализациями более абстрактных, но более гибких версий. QAbstractItemModel имеет вызов flags(QModelIndex index), где вы должны вернуть соответствующее значение для вашего столбца.

6 голосов
/ 12 июля 2013

Самый простой способ, который я нашел, это использовать Qt :: ItemFlags

void myClass::treeDoubleClickSlot(QTreeWidgetItem *item, int column)
{
    Qt::ItemFlags tmp = item->flags();
    if (isEditable(item, column)) {
        item->setFlags(tmp | Qt::ItemIsEditable);
    } else if (tmp & Qt::ItemIsEditable) {
        item->setFlags(tmp ^ Qt::ItemIsEditable);
    }
}

Верхняя часть if добавляет функцию редактирования через OR, а нижняя часть проверяет, есть ли она с AND, а затем удаляет ее с помощью XOR.

Таким образом, функциональность редактирования добавляется, когда вы этого хотите, и удаляется, когда вы этого не делаете.

Затем подключите эту функцию к сигналу itemDoubleClicked() виджета дерева и напишите свое решение «редактировать или не редактировать» внутри isEditable()

3 голосов
/ 11 февраля 2011
class EditorDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    EditorDelegate(QObject *parent):QItemDelegate(parent){};
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

QWidget* EditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.column() == 1)
    {
        return QItemDelegate::createEditor(parent, option, index);
    }
    return nullptr;
}

В QTreeWidget:

myQTreeWidget::myQTreeWidget()
{
    EditorDelegate *d = new EditorDelegate(this);
    this->setItemDelegate(d);
}
2 голосов
/ 10 марта 2018

Возможно, немного поздно, но может помочь:

void MyClass::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column) {
    Qt::ItemFlags flags = item->flags();
    if(column == 0)
    {
        item->setFlags(flags & (~Qt::ItemIsEditable));
    }
    else
    {
        item->setFlags(flags | Qt::ItemIsEditable);
    } 
}

Здесь 0 - индекс столбца, который вы хотите сделать доступным только для чтения.

flags & (~Qt::ItemIsEditable)

Устанавливает позицию ItemIsEditable в 0 независимо от предыдущего флага вашего элемента.

flags | Qt::ItemIsEditable

Устанавливает значение 1 независимо от предыдущего флага.

1 голос
/ 02 ноября 2017

Я обнаружил, что приведенный ниже код хорошо работает для моих нужд и "своего рода" останавливает пользователь от редактирования определенных частей столбцов:

Я проверяю роль, а затем столбец. Я разрешаю редактировать только в столбце 0. Поэтому, если пользователь редактирует его в любом другом столбце, я прекращаю редактирование setData, и никаких изменений не производится.

void treeItemSubclassed::setData(int column, int role, const QVariant &value) {
    if (role == Qt::ItemIsEditable && column != 0){
        return;
    }
    QTreeWidgetItem::setData(column, role, value);
}
1 голос
/ 11 января 2011

Я новичок в PySide и Python в целом, но мне удалось заставить это работать, зарегистрировавшись в QTreeWidget для обратных вызовов itemClicked. Внутри обратного вызова проверьте столбец и вызывайте editItem только в том случае, если он предназначен для столбца, который вы хотите разрешить редактирование.

class Foo(QtGui.QMainWindow):
...
def itemClicked(self, item, column):
   if column > 0:
      self.qtree.editItem(item, column)

Не вызывая editItem для столбца 0, событие в основном отбрасывается.

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

Установить дочерний элемент дерева-виджета редактируемым или нет (itmes of tree), основываясь на строке и столбце.

...