Question

J'ai un QTreeWidgetItem avec deux colonnes de données, est-il possible de ne faire 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.

Était-ce utile?

La solution

On dirait que vous devrez renoncer à l'utilisation QTreeWidget et QTreeWidgetItem et aller avec QTreeView et QAbstractItemModel. Les classes « Widget » sont des classes de proximité qui sont mises en œuvre concrètes des versions plus abstraites mais plus souples. QAbstractItemModel a un flags(QModelIndex index) d'appel où vous reviendriez la valeur appropriée pour votre colonne.

Autres conseils

Vous pouvez faire que certaines colonnes dans un éditable QTreeWidget en utilisant une solution de contournement:

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

2) lors de l'insertion des éléments, définir le Qt: drapeau ItemIsEditable de l'objet QTreeWidgetItem

3) Connecter la fente suivante pour le 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 écrit qui retourne vrai pour les colonnes modifiables et faux pour les colonnes non modifiables.

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

Créer un délégué, qui renvoie 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 utiliser plus tard comme un délégué personnalisé pour votre colonne

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

Sembler la QTreeWidget norme ne permet pas. Je pense qu'il ya deux façons de le faire:

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

  2. Utilisez un QTreeView avec un QStandardItemModel. Ensuite, lorsque vous ajoutez l'élément situé juste à la colonne appropriée pour permettre des modifications:

Voici un 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 du degré de flexibilité que vous voulez avec votre modèle.

La façon la 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 sommet de la if ajoute la fonctionnalité d'édition par un OR, et les contrôles de fond si elle est là avec AND, puis enlève avec un XOR.

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

Connectez ensuite cette fonction au signal de itemDoubleClicked() de widget arbre, et écrivez votre décision « de modifier ou de ne pas modifier » à l'intérieur de isEditable()

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 le QTreeWidget:

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

Peut-être un peu en retard, mais il 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'indice de la colonne que vous voulez faire en lecture seule.

flags & (~Qt::ItemIsEditable)

Définit la position ItemIsEditable à 0 quel que soit l'ancien drapeau de votre article.

flags | Qt::ItemIsEditable

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

Je suis nouveau à PySide et Python en général, mais j'ai pu obtenir ce travail en vous inscrivant à la QTreeWidget pour callbacks itemClicked. Au sein de la fonction de rappel, vérifiez la colonne et n'appellent « editItem » si elle est une colonne que vous souhaitez autoriser l'édition.

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

En n'invoquant editItem pour la colonne 0, l'événement est essentiellement mis au rebut.

Je trouve que le code ci-dessous fonctionne bien pour mes besoins et ne « un peu » arrêter la utilisateur de modifier certaines parties de colonnes:

Je vérifie essentiellement pour rôle et colonne. J'autorise seulement pour l'édition dans la colonne 0. Donc, si l'utilisateur d'éditer dans une autre colonne, puis j'arrêter le modifier setData et aucun changement est fait.

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

Définir l'enfant du modifiables ou non-arbre (widget fois d'arbres), en fonction de la ligne et la colonne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top