wake-up-neo.com

Nur eine Spalte eines QTreeWidgetItem bearbeitbar machen

Ich habe eine QTreeWidgetItem mit zwei Datenspalten. Gibt es eine Möglichkeit, nur die zweite Spalte bearbeitbar zu machen? Wenn ich das Folgende mache:

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

alle Spalten können bearbeitet werden.

25
Andreas Brinck

Sieht so aus, als müssten Sie auf QTreeWidget und QTreeWidgetItem verzichten und sich für QTreeView und QAbstractItemModel entscheiden. Die "Widget" -Klassen sind Convenience-Klassen, die konkrete Implementierungen der abstrakteren, aber flexibleren Versionen sind. QAbstractItemModel hat einen Aufruf flags(QModelIndex index), bei dem Sie den entsprechenden Wert für Ihre Spalte zurückgeben würden.

7

Sie können nur bestimmte Spalten in einem QTreeWidget mithilfe einer Problemumgehung bearbeitbar machen:

1) Setzen Sie die Eigenschaft editTriggers des QTreeWidget auf NoEditTriggers

2) Setzen Sie beim Einfügen von Elementen das Flag Qt: ItemIsEditable des QTreeWidgetItem-Objekts

3) Verbinden Sie den folgenden Steckplatz mit dem Signal "itemDoubleClicked" des QTreeWidget-Objekts:

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

dabei ist "isEditable" eine von Ihnen geschriebene Funktion, die für bearbeitbare Spalten true und für nicht bearbeitbare Spalten false zurückgibt.

25
d11

Ich hatte vor kurzem das gleiche Problem und entdeckte eine Lösung, die mit allen EditTriggern funktioniert, nicht nur mit dem DoubleClicked (und der Verbindung zum doppelt angeklickten Signal).

Erstellen Sie einen Delegaten, der einen NULL-Zeiger für den Editor zurückgibt:

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

Verwenden Sie es später als benutzerdefinierten Delegaten für Ihre Spalte

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

Es sieht so aus, als ob das Standard-QTreeWidget dies nicht zulässt. Ich denke, es gibt zwei Möglichkeiten, dies zu tun:

  1. Verwenden Sie ein QTreeView mit Ihrer eigenen Klasse, die von QAbstractItemModel abgeleitet ist, und überschreiben Sie die Flags-Funktion

  2. Verwenden Sie ein QTreeView mit einem QStandardItemModel. Wenn Sie dann das Element hinzufügen, legen Sie einfach die entsprechende Spalte fest, um Änderungen zuzulassen:

Hier ist ein Code für die zweite 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);

Ich finde den zweiten Ansatz einfacher, aber das hängt davon ab, wie viel Flexibilität Sie mit Ihrem Modell wünschen.

8
Blaise

Der einfachste Weg, den ich gefunden habe, war die Verwendung von 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);
    }
}

Oben in der if wird die Bearbeitungsfunktion durch eine OR ergänzt. Unten wird geprüft, ob sie mit AND vorhanden ist. Anschließend wird sie mit einer XOR entfernt.

Auf diese Weise wird die Bearbeitungsfunktion hinzugefügt, wenn Sie dies wünschen, und entfernt, wenn Sie dies nicht tun.

Verbinden Sie dann diese Funktion mit dem Signal itemDoubleClicked() des Baum-Widgets und schreiben Sie Ihre Entscheidung zum Bearbeiten oder Nichtbearbeiten in isEditable().

6
clark
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;
}

In der QTreeWidget:

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

Ich habe herausgefunden, dass der folgende Code gut für meine Bedürfnisse funktioniert und den Benutzer "irgendwie" davon abhält, bestimmte Teile von Spalten zu bearbeiten:

Ich überprüfe grundsätzlich die Rolle und dann die Spalte. Ich erlaube nur die Bearbeitung in Spalte 0. Wenn der Benutzer sie in einer anderen Spalte bearbeitet, beende ich die Bearbeitung von setData und es werden keine Änderungen vorgenommen.

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

Vielleicht ein bisschen zu spät, aber vielleicht hilft:

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

Hier ist 0 der Index der Spalte, die Sie schreibgeschützt erstellen möchten.

flags & (~Qt::ItemIsEditable)

Setzt die ItemIsEditable-Position auf 0, unabhängig von der vorherigen Markierung Ihres Artikels.

flags | Qt::ItemIsEditable

Setzt es ungeachtet des vorherigen Flags auf 1.

1
chraz

Ich bin neu in PySide und Python im Allgemeinen, aber ich war in der Lage, dies zum Laufen zu bringen, indem ich mich bei QTreeWidget für itemClicked-Rückrufe registrierte. Überprüfen Sie innerhalb des Rückrufs die Spalte und rufen Sie 'editItem' nur auf, wenn es sich um eine Spalte handelt, die Sie bearbeiten möchten.

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

Wenn Sie editItem für Spalte 0 nicht aufrufen, wird das Ereignis grundsätzlich verworfen.

1
Kerry

Legen Sie fest, ob das untergeordnete Element des Baum-Widgets (Elemente des Baums) je nach Zeile und Spalte bearbeitet werden kann.

0
Naruto