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.
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.
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.
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));
On dirait que le QTreeWidget standard ne le permet pas. Je pense qu'il y a deux façons de faire cela:
Utilisez un QTreeView avec votre propre classe dérivée de QAbstractItemModel et remplacez la fonction flags
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.
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()
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);
}
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);
}
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.
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é.
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.