2010-05-10 5 views
21

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

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

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

ответ

6

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

+2

Не обязательно (если я не ошибаюсь). См. Мой ответ ниже. – d11

+0

Это намного больше, чем новое решение NoEditDelegate, которое я считаю лучшим. –

+0

Спасибо @David. Я также поддержал решение NoEditDelegate. Это кажется более аккуратным и более полным, и я бы рекомендовал его для нескольких триггеров редактирования. – d11

0

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

+0

Как это сделать? 'QTreeWidgetItem :: setFlags' не принимает столбец в качестве аргумента. Должен ли я делать это в 'QTreeWidget', если да, с каким методом? –

8

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

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

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

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

1

Я новичок в 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

Теперь попробуйте нажать F2, и вы сможете редактировать предположительно-редактируемые столбцы ;-) –

18

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

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

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)); 
+2

Отличный вариант. Вы также можете назначить делегата всему представлению и проверить, заблокирован ли он столбец, указав его на 'index.column()'. Вы также можете получить доступ к самому QTreeWidgetItem, переработав 'index.internalPointer()' в 'QTreeWidgetItem * 'для еще большего контроля при блокировке редактирования, например, только блокирование редактирования, когда элемент имеет дочерние элементы (как в моем случае) , – Phlucious

+0

отличный ответ, небольшая тонкая мелодия, и вы можете использовать этот делегат для всех: виртуальный QWidget * createEditor (QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const { if (index.column()> 0) { return 0; } return QStyledItemDelegate :: createEditor (родительский, опционный, индексный); }} – Dariusz

3
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); 
} 
+0

Две вещи: возвратите 'nullptr' из createEditor(), если столбцы не должны редактироваться, возможно, как часть' else'. И установите флаги элементов в 'Qt :: ItemIsEditable' для элементов, которые нужно отредактировать, иначе делегат не будет вызван. –

22

Вы можете сделать только определенные столбцы в 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 для не редактируемых столбцов.

+0

Лучшее решение в моем случае. Благодаря! –

+6

Двойной щелчок - это не единственный способ начать редактирование, есть много других триггеров редактирования (любой ключ, ключ редактирования (F2 в Windows/Linux), текущий элемент изменен и т. Д. И т. Д.) В зависимости от конфигурации (setEditTriggers). Так что это кажется немного неполным. –

+0

Согласен, @DavidFaure. Мое решение просто понять и хорошо протестировано, но для выполнения нескольких триггеров редактирования потребуется некоторая работа. Если требуется несколько триггеров редактирования, я рекомендую решение NoEditDelegate пользователем571167. – d11

5

Самый простой способ, который я нашел, чтобы использовать 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()

+0

идеальный ответ на меня – NDestiny

0

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

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

void treeItemSubclassed::setData(int column, int role, const QVariant &value) { 
    if (role == Qt::ItemIsEditable && column != 0){ 
     return; 
    } 
    QTreeWidgetItem::setData(column, role, value); 
} 
0

Может быть, немного поздно, но может помочь:

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 независимо от предыдущего флага.