2010-05-10 19 views
21

Tengo un QTreeWidgetItem con dos columnas de datos, ¿hay alguna manera de hacer que solo la segunda columna se pueda editar? Cuando hago lo siguiente:Hacer solo una columna de QTreeWidgetItem editable

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

todas las columnas son editables.

Respuesta

6

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 una llamada flags(QModelIndex index) donde devolverá el valor apropiado para su columna.

+2

No necesariamente (si no me equivoco). Ver mi respuesta a continuación. – d11

+0

Esto es mucho más retrabajo que la solución NoEditDelegate publicada a continuación, que considero mejor. –

+0

Gracias @David. También voté por la solución NoEditDelegate. Parece más ordenado y más completo, y lo recomendaría para desencadenantes de edición múltiple. – d11

0

Establezca el elemento secundario del widget de árbol editable o no (archivos de árbol), según la fila y la columna.

+0

¿Cómo hago esto? 'QTreeWidgetItem :: setFlags' no toma la columna como argumento. ¿Se supone que debo hacer esto en el 'QTreeWidget'? De ser así, ¿con qué método? –

8

Parece que el QTreeWidget estándar no permite esto. Creo que hay dos maneras de hacer esto:

  1. utilizar un QTreeView con su propia clase derivada de QAbstractItemModel y modifique las opciones funcionan

  2. Utilice un QTreeView con un QStandardItemModel. Luego, cuando se agrega el elemento acaba de establecer la columna apropiada para permitir ediciones:

Aquí hay algo de 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 el segundo enfoque más simple, pero eso depende de la cantidad de flexibilidad quieres con tu modelo

1

Soy nuevo en PySide y en Python en general, pero pude hacerlo funcionar registrándome con el QTreeWidget para la devolución 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.

+0

Ahora intenta presionar F2, y podrás editar las columnas supuestamente no editables ;-) –

18

que tenían el mismo problema hace poco y descubrieron una solución que funciona con todos los EditTriggers, no sólo la doubleclicked (y la conexión a la señal de hacer doble clic)

Crear un delegado, que devuelve un puntero nulo 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 más tarde utilizarlo como un delegado a medida para su columna

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

Gran opción. También puede asignar el delegado a la vista completa y verificar si se trata de una columna bloqueada marcando contra 'index.column()'. También puede obtener acceso al QTreeWidgetItem refinanciando 'index.internalPointer()' a un 'QTreeWidgetItem *' para tener aún más control sobre cuando la edición está bloqueada, como solo bloquear la edición cuando el elemento tiene hijos (como en mi caso) . – Phlucious

+0

gran respuesta, una pequeña melodía y puede usar este delegado para todos: QWidget virtual * createEditor (QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const { if (index.column()> 0) { return 0; } return QStyledItemDelegate :: createEditor (principal, opción, índice); }} – 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; 
} 

En el QTreeWidget:

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

Dos cosas: devuelve 'nullptr' de createEditor() si las columnas no se deben editar, quizás como parte del' else'. Y establezca los indicadores de elementos en 'Qt :: ItemIsEditable' para los elementos que deben editarse; de ​​lo contrario, no se llamará al delegado. –

22

sólo puedes hacer ciertas columnas en un QTreeWidget editable usando una solución:

1) Establecer la propiedad editTriggers del QTreeWidget a NoEditTriggers

2) Al insertar elementos, establezca 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 ha escrito que devuelve verdadero para las columnas editables y falso para las columnas no editables.

+0

La mejor solución en mi caso. ¡Gracias! –

+6

Sin embargo, hacer doble clic no es la única manera de comenzar a editar, hay muchos otros activadores de edición (cualquier clave, la tecla de edición (F2 en Windows/Linux), el elemento actual modificado, etc., etc.) según la configuración (setEditTriggers). Entonces esto parece un poco incompleto. –

+0

Acepto, @DavidFaure. Mi solución es simple de entender y bien probada, pero requeriría algo de trabajo para implementar para desencadenantes de edición múltiple. Si se desean múltiples activadores de edición, recomiendo la solución NoEditDelegate por user571167. – d11

5

La forma más sencilla que encontré fue utilizar 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 la if añade la funcionalidad de edición a través de un OR, y los cheques de fondo si está allí con AND, a continuación, elimina con un XOR.

De esta manera se añade la funcionalidad de edición cuando lo desee, y se retira cuando no lo hace.

A continuación, conecte esta función a la señal del widget de árbol itemDoubleClicked(), y escribir su 'para modificar o no modificar la decisión dentro de isEditable()

+0

respuesta perfecta para mí – NDestiny

0

descubrí que el código de abajo funciona bien para mis necesidades y hace "un poco "detener el usuario de la edición de ciertas partes de columnas:

básicamente puedo comprobar si hay papel 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); 
} 
0

Tal vez un poco tarde, pero puede ayudar a:

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 hacer de sólo lectura.

flags & (~Qt::ItemIsEditable) 

establece la posición ItemIsEditable a 0 sin tener en cuenta la anterior bandera de su artículo.

flags | Qt::ItemIsEditable 

Lo establece en 1 independientemente de la marca anterior.

Cuestiones relacionadas