c++ - Haciendo editable solo una columna de QTreeWidgetItem
flags (10)
Tengo un QTreeWidgetItem
con dos columnas de datos, ¿hay alguna manera de hacer que solo la segunda columna sea editable? Cuando hago lo siguiente:
QTreeWidgetItem* item = new QTreeWidgetItem();
item->setFlags(item->flags() | Qt::ItemIsEditable);
todas las columnas se pueden editar
Descubrí que el siguiente código funciona bien para mis necesidades y "poco" impide que el usuario edite ciertas partes de las columnas:
Básicamente reviso el rol y luego la columna. Solo permito editar en la columna 0. Entonces, si el usuario lo edita en cualquier otra columna, entonces detengo la edición setData y no se realizan cambios.
void treeItemSubclassed::setData(int column, int role, const QVariant &value) {
if (role == Qt::ItemIsEditable && column != 0){
return;
}
QTreeWidgetItem::setData(column, role, value);
}
Establezca el elemento secundario del widget de árbol editable o no (itmes of tree), según la fila y la columna.
La forma más simple que encontré fue usar 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);
}
}
La parte superior de if
agrega la funcionalidad de edición a través de un OR
, y la parte inferior comprueba si está allí con AND
, y luego la elimina con un XOR
.
De esta forma, la funcionalidad de edición se agrega cuando la desea, y se elimina cuando no lo hace.
A continuación, conecte esta función a la señal itemDoubleClicked()
del widget de árbol y escriba su decisión ''para editar o no editar'' dentro de isEditable()
Parece que el QTreeWidget estándar no permite esto. Creo que hay dos formas de hacer esto:
Utilice QTreeView con su propia clase derivada de QAbstractItemModel y anule la función de indicadores
Use QTreeView con QStandardItemModel. Luego, cuando agrega el elemento, simplemente configure la columna adecuada para permitir ediciones:
Aquí hay un código para la segunda opción:
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);
Encuentro que el segundo enfoque es más simple, pero eso depende de la flexibilidad que desee con su modelo.
Parece que tendrá que renunciar a usar QTreeWidget
y QTreeWidgetItem
e ir con QTreeView
y QAbstractItemModel
. Las clases "Widget" son clases de conveniencia que son implementaciones concretas de las versiones más abstractas pero más flexibles. QAbstractItemModel
tiene un distintivo de llamada flags(QModelIndex index)
donde devolverá el valor apropiado para su columna.
Puede hacer que solo ciertas columnas de un QTreeWidget se puedan editar mediante una solución alternativa:
1) Establezca la propiedad editTriggers del QTreeWidget en NoEditTriggers
2) Al insertar elementos, configure el indicador Qt: ItemIsEditable del objeto QTreeWidgetItem
3) Conecte la siguiente ranura a la señal "itemDoubleClicked" del objeto QTreeWidget:
void MainWindow::onTreeWidgetItemDoubleClicked(QTreeWidgetItem * item, int column)
{
if (isEditable(column)) {
ui.treeWidget->editItem(item, column);
}
}
donde "isEditable" es una función que escribió que devuelve verdadero para las columnas editables y falso para las columnas no editables.
Recientemente tuve el mismo problema y descubrí una solución que funciona con todos los EditTriggers, no solo con DoubleClicked (y la conexión con la señal de doble clic).
Cree un delegado, que devuelve un puntero NULL para el editor:
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;
}
};
Y luego úsala como un delegado personalizado para tu columna
ui->parameterView->setItemDelegateForColumn(0, new NoEditDelegate(this));
Soy nuevo en PySide y en Python en general, pero pude hacer que esto funcionara registrándome con el QTreeWidget para las devoluciones de llamadas itemClicked. Dentro de la devolución de llamada, verifique la columna y solo llame a ''editItem'' si es para una columna que desea permitir la edición.
class Foo(QtGui.QMainWindow):
...
def itemClicked(self, item, column):
if column > 0:
self.qtree.editItem(item, column)
Al no invocar editItem para la columna 0, el evento se descarta básicamente.
Tal vez un poco tarde, pero puede ayudar:
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);
}
}
Aquí 0 es el índice de la columna que desea que sea de solo lectura.
flags & (~Qt::ItemIsEditable)
Establece la posición ItemIsEditable en 0 independientemente del indicador anterior de su artículo.
flags | Qt::ItemIsEditable
Lo establece en 1 independientemente de la bandera anterior.
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;
}
En el QTreeWidget
:
myQTreeWidget::myQTreeWidget()
{
EditorDelegate *d = new EditorDelegate(this);
this->setItemDelegate(d);
}