web-dev-qa-db-fra.com

Rendre une seule colonne d'un QTreeWidgetItem modifiable

J'ai une QTreeWidgetItem avec deux colonnes de données, y a-t-il un moyen de ne rendre que la deuxième colonne modifiable? Quand je fais ce qui suit:

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

toutes les colonnes deviennent modifiables.

25
Andreas Brinck

On dirait que vous devrez renoncer à utiliser QTreeWidget et QTreeWidgetItem et partir avec QTreeView et QAbstractItemModel. Les classes "Widget" sont des classes de commodité qui sont des implémentations concrètes des versions plus abstraites mais plus flexibles. QAbstractItemModel a un appel flags(QModelIndex index) où vous renverriez la valeur appropriée pour votre colonne.

7
Harald Scheirich

Vous pouvez rendre modifiables uniquement certaines colonnes d'un QTreeWidget à l'aide d'une solution de contournement:

1) Définissez la propriété editTriggers du QTreeWidget sur NoEditTriggers

2) Lors de l'insertion d'éléments, définissez l'indicateur Qt: ItemIsEditable de l'objet QTreeWidgetItem

3) Connectez l’emplacement suivant au signal "itemDoubleClicked" de l’objet QTreeWidget:

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

où "isEditable" est une fonction que vous avez écrite et qui renvoie true pour les colonnes modifiables et false pour les colonnes non modifiables.

25
d11

J'ai eu le même problème récemment et j'ai découvert une solution qui fonctionne avec tous les EditTriggers, pas seulement avec DoubleClicked (et la connexion au signal double-cliqué).

Créez un délégué, qui retourne un pointeur NULL pour l'éditeur:

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

Et plus tard, utilisez-le comme délégué personnalisé pour votre colonne

ui->parameterView->setItemDelegateForColumn(0, new NoEditDelegate(this));
18
user571167

On dirait que le QTreeWidget standard ne le permet pas. Je pense qu'il y a deux façons de faire cela:

  1. Utilisez un QTreeView avec votre propre classe dérivée de QAbstractItemModel et remplacez la fonction flags

  2. Utilisez un QTreeView avec un QStandardItemModel. Ensuite, lorsque vous ajoutez l'élément, définissez simplement la colonne appropriée pour autoriser les modifications:

Voici du code pour la deuxième option:

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

Je trouve la deuxième approche plus simple mais cela dépend de la flexibilité que vous souhaitez avec votre modèle.

8
Blaise

Le moyen le plus simple que j'ai trouvé était d'utiliser 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);
    }
}

Le haut de la if ajoute la fonctionnalité d'édition via une OR, et le bas vérifie si elle existe avec AND, puis l'enlève avec une XOR.

De cette façon, la fonctionnalité d'édition est ajoutée quand vous le souhaitez et supprimée quand vous ne le souhaitez pas.

Ensuite, connectez cette fonction au signal itemDoubleClicked() du widget de l'arborescence et écrivez votre décision 'modifier ou non' à l'intérieur de isEditable()

6
clark
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;
}

Dans la QTreeWidget:

myQTreeWidget::myQTreeWidget()
{
    EditorDelegate *d = new EditorDelegate(this);
    this->setItemDelegate(d);
}
3
user336063

J'ai découvert que le code ci-dessous répond bien à mes besoins et empêche "un peu" l'utilisateur de modifier certaines parties des colonnes:

En gros, je vérifie le rôle, puis la colonne. J'autorise uniquement l'édition dans la colonne 0. Donc, si l'utilisateur le modifie dans une autre colonne, j'arrête la modification de setData et aucune modification n'est apportée.

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

Peut-être un peu tard, mais peut aider:

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

Ici 0 est l'index de la colonne que vous voulez faire en lecture seule.

flags & (~Qt::ItemIsEditable)

Définit la position ItemIsEditable sur 0 quel que soit le drapeau précédent de votre élément.

flags | Qt::ItemIsEditable

Définit à 1 quel que soit le drapeau précédent.

1
chraz

PySide et Python sont nouveaux pour moi, mais j’ai réussi à le faire fonctionner en me inscrivant auprès de QTreeWidget pour les rappels d’objetClicked. Dans le rappel, cochez la colonne et appelez uniquement «editItem» s'il s'agit d'une colonne que vous souhaitez autoriser à modifier.

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

En n'appelant pas editItem pour la colonne 0, l'événement est fondamentalement ignoré.

1
Kerry

Définissez l’enfant de l’arborescence-widget éditable ou non (éléments de l’arbre), en fonction de la ligne et de la colonne.

0
Naruto