2010-05-10 7 views

risposta

6

Sembra che si dovrà rinunciare utilizzando QTreeWidget e QTreeWidgetItem e andare con QTreeView e QAbstractItemModel. Le classi "Widget" sono classi di convenienza che sono implementazioni concrete delle versioni più astratte ma più flessibili. QAbstractItemModel ha una chiamata flags(QModelIndex index) in cui si restituirebbe il valore appropriato per la colonna.

+2

Non necessariamente (se non mi sbaglio). Vedi la mia risposta qui sotto. – d11

+0

Questa è una rielaborazione molto più complessa della soluzione NoEditDelegate pubblicata di seguito, che ritengo migliore. –

+0

Grazie a @David. Ho anche upvoted la soluzione NoEditDelegate. Sembra più ordinato e completo e lo consiglierei per più trigger di modifica. – d11

0

Imposta il figlio del widget dell'albero modificabile o meno (elementi dell'albero), in base alla riga e alla colonna.

+0

Come posso fare questo? 'QTreeWidgetItem :: setFlags' non considera la colonna come argomento. Dovrei farlo nel 'QTreeWidget', in caso affermativo con quale metodo? –

8

sembrare lo standard QTreeWidget non consente questo. Penso che ci siano due modi per farlo:

  1. utilizzare un QTreeView con la propria classe derivata da QAbstractItemModel e sovrascrivere le bandiere funzionano

  2. Utilizzare un QTreeView con un QStandardItemModel. Poi, quando si aggiunge la voce è sufficiente impostare la colonna appropriata per consentire modifiche:

Ecco po 'di codice per la seconda opzione:

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

trovo il secondo approccio più semplice, ma che dipende da quanto la flessibilità vuoi con il tuo modello.

1

Sono nuovo a PySide e Python in generale, ma sono riuscito a farlo funzionare registrandosi con QTreeWidget per i callback con oggetto. All'interno del callback, controlla la colonna e chiama solo "editItem" se è per una colonna a cui vuoi consentire la modifica.

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

Non invocando editItem per la colonna 0, l'evento viene sostanzialmente scartato.

+0

Ora prova a premere F2 e sarai in grado di modificare le colonne presumibilmente non modificabili ;-) –

18

Ho avuto lo stesso problema da poco e ha scoperto una soluzione che funziona con tutti i EditTriggers, non solo quella DoubleClicked (ed il collegamento al segnale doppio clic)

crea un delegato, che restituisce un puntatore nullo per il 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; 
     } 
    }; 

E poi usarlo come un delegato personalizzato per la colonna

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

Ottima opzione. È inoltre possibile assegnare il delegato all'intera vista e verificare se si tratta di una colonna bloccata controllando 'index.column()'. Puoi anche accedere a QTreeWidgetItem stessa rifondendo 'index.internalPointer()' a un 'QTreeWidgetItem *' per un controllo ancora maggiore su quando la modifica è bloccata, come ad esempio il blocco delle modifiche quando l'elemento ha figli (come nel mio caso) . – Phlucious

+0

ottima risposta, una piccola sintonia fine ed è possibile utilizzare questo delegato per tutti: virtuale QWidget * createEditor (QWidget * parent, const QStyleOptionViewItem e opzione, const QModelIndex e index) const { if (index.column()> 0) { ritorno 0; } return QStyledItemDelegate :: createEditor (parent, option, index); }} – 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; 
} 

Nella QTreeWidget:

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

Due cose: restituisce 'nullptr' da createEditor() se le colonne non devono essere modificate, forse come parte di' else'. E imposta gli elementi in "Qt :: ItemIsEditable" per gli elementi che devono essere modificati altrimenti il ​​delegato non verrà chiamato. –

22

È possibile effettuare solo alcune colonne in una QTreeWidget modificabili utilizzando una soluzione:

1) Impostare la proprietà editTriggers del QTreeWidget per NoEditTriggers

2) Inserendo elementi, impostare il flag Qt: ItemIsEditable dell'oggetto QTreeWidgetItem

3) Collegare lo slot seguente al segnale "itemDoubleClicked" dell'oggetto QTreeWidget:

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

dove "isEditable" è una funzione scritta dall'utente che restituisce true per le colonne modificabili e false per le colonne non modificabili.

+0

La migliore soluzione nel mio caso. Grazie! –

+6

Tuttavia, fare doppio clic non è l'unico modo per iniziare a modificare, ci sono molti altri trigger di modifica (qualsiasi tasto, il tasto di modifica (F2 su Windows/Linux), l'elemento corrente modificato, ecc. Ecc.) A seconda della configurazione (setEditTriggers). Quindi questo sembra un po 'incompleto. –

+0

Sono d'accordo, @DavidFaure. La mia soluzione è semplice da comprendere e ben testata, ma richiederebbe alcuni interventi da implementare per più trigger di modifica. Se sono desiderati più trigger di modifica, raccomando la soluzione NoEditDelegate dall'utente571167. – d11

5

Il modo più semplice che ho trovato è stato quello di utilizzare 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 superiore della if aggiunge la funzionalità di editing attraverso un OR, ei controlli di fondo, se è lì con AND, quindi rimuove con un XOR.

In questo modo la funzionalità di modifica viene aggiunta quando lo si desidera e rimossa quando non lo si desidera.

Quindi, collegare questa funzione per il segnale del widget albero itemDoubleClicked(), e scrivere il vostro 'di modificare o di non modificare' decisione all'interno del isEditable()

+0

risposta perfetta per me – NDestiny

0

ho scoperto che il codice qui sotto funziona bene per le mie esigenze e fa "un pò "interrompere l'utente di dalla modifica di alcune parti di colonne:

Fondamentalmente controllo il ruolo e quindi la colonna. Consentisco solo la modifica nella colonna 0. Quindi, se l'utente lo modifica in qualsiasi altra colonna, quindi interrompo la modifica setData e non viene apportata alcuna modifica.

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

Forse un po 'tardi, ma può aiutare:

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

Qui 0 è l'indice della colonna che si desidera fare in sola lettura.

flags & (~Qt::ItemIsEditable) 

Imposta la posizione ItemIsEditable su 0 indipendentemente dalla precedente bandiera del tuo articolo.

flags | Qt::ItemIsEditable 

Imposta su 1 indipendentemente dal flag precedente.

Problemi correlati