Das Ziehen und Ablegen von QTreeWidgetItem funktioniert nicht ordnungsgemäß

Emanuele

Ich habe a unterklassifiziert, QTreeWidgetum die protectedFunktionen von a neu zu implementieren dragund dropum Drop-Eltern und Kinder von a zu ziehen QTreeWidget.

Es funktioniert fast und das Problem ist, dass sobald ich versuche, Kinder oder Eltern per Drag & Drop zu entfernen, diese gelöscht werden, sobald ich sie fallen lasse. Der Quellcode finden Sie hier, falls Sie sehen möchten, was los ist.

Auch wenn ich versuche, das übergeordnete Element per Drag & Drop zu verschieben, bewegt es sich leider nicht und es passiert nichts.

Siehe unten den seltsamen Effekt für die Kinder:

Ich ziehe das Kind "Original", um es direkt unter "Sample" abzulegen, und dieses Verfahren scheint korrekt zu funktionieren:

drrop

Nach dem Löschen von "Original" scheint der Index vorhanden zu sein, aber er scheint teilweise gelöscht zu sein:

ddrop2

Ich bin mir nicht sicher, was genau los ist und warum die Kinder nicht richtig fallen gelassen werden und warum sich die Eltern buchstäblich nicht bewegen.

Unter dem Code des minimal überprüfbaren Beispiels:

mainwindow.h

#include <QMainWindow>

class QTreeWidget;
class QTreeWidgetItem;


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    QTreeWidgetItem *createItem(const QString &name, const QString &iconPath);
    
private:
    Ui::MainWindow *ui;
    QTreeWidget *widget;
    QString m_Name;
    QString m_Path;

    };
#endif // MAINWINDOW_H

mainwindow.cpp

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->treeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->treeWidget->setDragEnabled(true);
    ui->treeWidget->viewport()->setAcceptDrops(true);
    ui->treeWidget->setDropIndicatorShown(true);
    ui->treeWidget->setDragDropMode(QAbstractItemView::InternalMove);

    auto *top1 = createItem("Images", "/home/ui/qrc/laserscan.png");
    auto *top2 = createItem("Path", "/home/ui/qrc/laserscan.png");

    top1->addChild(createItem("Original", "/home/ui/qrc/laserscan.png"));
    top1->addChild(createItem("Sample", "/home/ui/qrc/laserscan.png"));

    top2->addChild(createItem("Left Side", "/home/ui/qrc/laserscan.png"));
    top2->addChild(createItem("Right Side", "/home/ui/qrc/laserscan.png"));

    ui->treeWidget->addTopLevelItems({ top1, top2 });

   // Below I am assigning to each parent/children a checkbox
    const int n_tops = ui->treeWidget->topLevelItemCount();
    for(int a = 0; a<n_tops; ++a) {
        const int n_children = ui->treeWidget->topLevelItem(a)->childCount();
        qtreewidgetitem_assign_qcheckbox(ui->treeWidget, ui->treeWidget->topLevelItem(a));
        for(int b = 0; b<n_children; ++b) {
            qtreewidgetitem_assign_qcheckbox(ui->treeWidget, ui->treeWidget->topLevelItem(a)->child(b));
        }
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}

QTreeWidgetItem *MainWindow::createItem(const QString &name, const QString &iconPath)
{
    auto *item = new QTreeWidgetItem(QStringList{name});
    item->setIcon(0, QIcon(iconPath));
    return item;
}

maphelpers.h

#include <QTreeWidget>
#include <QTreeWidgetItem>

void qtreewidgetitem_assign_qcheckbox(QTreeWidget *tree_widget, QTreeWidgetItem *tree_item);

#endif // MAPHELPERS_H

maphelpers.cpp

#include <QTreeWidget>

void qtreewidgetitem_assign_qcheckbox(QTreeWidget *tree_widget, QTreeWidgetItem *tree_item)
{
    MyCheckBoxMap *myCheckBoxMap = new MyCheckBoxMap(tree_item);
    tree_widget->setItemWidget(tree_item, MAP_COLUMN, myCheckBoxMap);
}

Unten, wie ich unterklassifiziert habe QTreeWidget:

customtreewidget.h

#include <QTreeWidget>

class CustomTreeWidget : public QTreeWidget
{
public:
    CustomTreeWidget(QWidget *parent = Q_NULLPTR);
protected:
    void dragEnterEvent(QDragEnterEvent *event) override;
    void dropEvent(QDropEvent *event) override;
private:
    QTreeWidgetItem *draggedItem;
};

#endif // CUSTOMTREEWIDGET_H

customtreewidget.cpp

CustomTreeWidget::CustomTreeWidget(QWidget *parent)
{
    QTreeWidgetItem* parentItem = new QTreeWidgetItem();
    parentItem->setText(0, "Test");
    parentItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled);

    int num_rows = topLevelItemCount();

    for(int i = 0; i < num_rows; ++i)
    {
      int nChildren = topLevelItem(i)->childCount();
      QTreeWidgetItem* pItem = new QTreeWidgetItem(parentItem);
      for(int j = 0; j < nChildren; ++j) {
          pItem->setText(0, QString("Number %1").arg(i) );
          pItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
          pItem->addChild(pItem);
          topLevelItem(i)->child(j);
      }
    }
}

void CustomTreeWidget::dragEnterEvent(QDragEnterEvent *event)
{
    draggedItem = currentItem();
    QTreeWidget::dragEnterEvent(event);
}

void CustomTreeWidget::dropEvent(QDropEvent *event)
{
    QModelIndex droppedIndex = indexAt(event->pos());
    if(!droppedIndex.isValid()) {
        return;
    }

    if(draggedItem) {
        QTreeWidgetItem *mParent = draggedItem->parent();
        if(mParent) {
            if(itemFromIndex(droppedIndex.parent()) != mParent)
                return;
                mParent->removeChild(draggedItem);
                mParent->insertChild(droppedIndex.row(), draggedItem);
        }
    }
}

Was ich bisher gemacht habe und was ich versucht habe:

1) Laut offizieller Dokumentation ist es möglich, die QTreeWidgetItemIterator-Klasse zu verwenden, und ich habe versucht, diesen Weg zu gehen. Tatsächlich können Sie unten meine ursprüngliche Implementierungsidee sehen, aber das brachte mich nicht wirklich weiter:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    auto *top1 = createItem("Images", "/home/ui/qrc/laserscan.png");
    auto *top2 = createItem("Path", "/home/ui/qrc/laserscan.png");
    
    top1->addChild(createItem("Original", "/home/ui/qrc/laserscan.png"));
    top1->addChild(createItem("Sample", "/home/ui/qrc/laserscan.png"));
    
    top2->addChild(createItem("Left Side", "/home/ui/qrc/laserscan.png"));
    top2->addChild(createItem("Right Side", "/home/ui/qrc/laserscan.png"));
    
    ui->treeWidget->addTopLevelItems({ top1, top2 });

    const int n_tops = ui->treeWidget->topLevelItemCount();

    // Below I am assigning to each parent/children a checkbox
    for(int a = 0; a<n_tops; ++a) {
        const int n_children = ui->treeWidget->topLevelItem(a)->childCount();
        qtreewidgetitem_assign_qcheckbox(ui->treeWidget, ui->treeWidget->topLevelItem(a));
        for(int b = 0; b<n_children; ++b) {
            qtreewidgetitem_assign_qcheckbox(ui->treeWidget, ui->treeWidget->topLevelItem(a)->child(b));
        }
    }

    QTreeWidgetItem *parentItem = Q_NULLPTR;
    QTreeWidgetItem *childItem = Q_NULLPTR;

    QTreeWidgetItemIterator it(ui->treeWidget);
       while (*it) {
           parentItem = new QTreeWidgetItem(ui->treeWidget);
           //parentItem->setText(0, it.key());
           foreach (const auto &str, it) {
               childItem = new QTreeWidgetItem;
               childItem->setText(0, str);
               parentItem->addChild(childItem);
           }
       }
}

2) Nach weiteren Recherchen in der offiziellen Dokumentation entschied ich mich, das Problem mit der QMapIterator-Klasse zu lösen. Ich wollte den Konstruktor so behalten, wie ich ihn ursprünglich strukturiert hatte, und stellte fest, dass das Durchlaufen eines QMapKonstruktors dazu gedacht war, den Konstruktor auf eine andere Weise umzuschreiben, im Grunde die unten stehende Implementierungsidee , wollte aber nicht so weiterkommen:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    auto *top1 = createItem("Images", "/home/ui/qrc/laserscan.png");
    auto *top2 = createItem("Path", "/home/ui/qrc/laserscan.png");
    
    top1->addChild(createItem("Original", "/home/ui/qrc/laserscan.png"));
    top1->addChild(createItem("Sample", "/home/ui/qrc/laserscan.png"));
    
    top2->addChild(createItem("Left Side", "/home/ui/qrc/laserscan.png"));
    top2->addChild(createItem("Right Side", "/home/ui/qrc/laserscan.png"));
    
    ui->treeWidget->addTopLevelItems({ top1, top2 });
    ui->treeWidget->addTopLevelItems({ top1, top2 });

    const int n_tops = ui->treeWidget->topLevelItemCount();

    // Below I am assigning to each parent/children a checkbox
    for(int a = 0; a<n_tops; ++a) {
        const int n_children = ui->treeWidget->topLevelItem(a)->childCount();
        qtreewidgetitem_assign_qcheckbox(ui->treeWidget, ui->treeWidget->topLevelItem(a));
        for(int b = 0; b<n_children; ++b) {
            qtreewidgetitem_assign_qcheckbox(ui->treeWidget, ui->treeWidget->topLevelItem(a)->child(b));
        }
    }

    QTreeWidgetItem *parentItem = Q_NULLPTR;
    QTreeWidgetItem *childItem = Q_NULLPTR;

    QMapIterator<QString, QStringList> i(treeMap);
    while (i.hasNext()) {
        i.next();
        parentItem = new QTreeWidgetItem(widget);
        parentItem->setText(0, i.key());
        foreach (const auto &str, i.value()) {
            childItem = new QTreeWidgetItem;
            childItem->setText(0, str);
            parentItem->addChild(childItem);
        }
    }
}

3) Nach weiteren Recherchen bin ich auf diese Quelle und diese andere Quelle gestoßen, die (insbesondere der letzte Beitrag) als Leitfaden für die Implementierung der Unterklasse des QTreeWidget.

Jetzt stecke ich fest, während ich versuche herauszufinden, warum ich trotz all der Dinge, die ich versucht habe, eine zu 90% funktionierende Anwendung erreicht habe, und was fehlt daher daran?

Vielen Dank für die Anleitung zur Lösung dieses Problems.

Ngoc Minh Nguyen

Ich denke, die Kontrollkästchen behandeln die Mausereignisse und lassen die Ereignisse nicht zum Element durchgehen. Um das gewünschte Verhalten zu erzielen, sollten Sie diesen Teil entfernen:

const int n_tops = ui->treeWidget->topLevelItemCount();

for(int a = 0; a<n_tops; ++a) {
    const int n_children = ui->treeWidget->topLevelItem(a)->childCount();
    qtreewidgetitem_assign_qcheckbox(ui->treeWidget, ui->treeWidget->topLevelItem(a));
    for(int b = 0; b<n_children; ++b) {
        qtreewidgetitem_assign_qcheckbox(ui->treeWidget, ui->treeWidget->topLevelItem(a)->child(b));
    }
}

Und in der createItem()Funktion:

QTreeWidgetItem *MainWindow::createItem(const QString &name, const QString &iconPath)
{
    auto *item = new QTreeWidgetItem(QStringList{name});
    item->setCheckState(0, Qt::Unchecked);
    item->setIcon(0, QIcon(iconPath));
    item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
    return item;
}

Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.

Bei Verstößen wenden Sie sich bitte [email protected] Löschen.

bearbeiten am
0

Lass mich ein paar Worte sagen

0Kommentare
LoginNach der Teilnahme an der Überprüfung

Verwandte Artikel

Das Ziehen und Ablegen von Bildern im Querformat funktioniert nicht

Das Ziehen und Ablegen funktioniert in Xcode nicht

Das Attribut "Akzeptieren" des Dateifelds funktioniert beim Ziehen und Ablegen der Datei nicht ordnungsgemäß

Das Ziehen und Ablegen von Ag-Grids funktioniert nach dem Sortieren von Zeilen nicht

Das Sortieren von Dezimaldaten funktioniert nicht ordnungsgemäß

Sichtbarkeit versteckt und sichtbar funktioniert nicht in Javascript beim Ziehen und Ablegen

Ziehen und Ablegen von "abgelegten Elementen"

Qt Ziehen und Ablegen von QTreeView

So verhindern Sie das Auslösen von Ereignissen beim Ziehen und Ablegen von Spalten in JavaFX TableView

qt schnelles Ziehen und Ablegen von Elementen beim Ziehen

Durch das native Ziehen und Ablegen des relativen Containers in Chrome wird der Geist nicht richtig gerendert

Das Ziehen und Ablegen von Text im Android Studio-Editor verursacht eine Ausnahme

Das Ziehen und Verschieben von Bildern mit einfachem JavaScript funktioniert nicht gut

Das dynamische Hinzufügen von Ansichten und das Festlegen von Parametern und Regeln funktioniert nicht ordnungsgemäß (Android)

Ziehen und Ablegen von eckigem Material cdkDragConstrainPosition ist nicht auf die Komponente beschränkt

Kann nicht in Spyder ziehen und ablegen, wenn es von cmd ausgeführt wird

Das Ausrichten von Inhalten und das Ausrichten von Elementen funktioniert bei der Verwendung von dispaly: flex nicht ordnungsgemäß

Eingabedatei ziehen und ablegen

Ziehen, ablegen und validieren

Dreieck ziehen und ablegen

Das Kontextmenü blockiert das Ziehen und Ablegen in ein neues Fenster

VueJS-Dropzone funktioniert beim Ziehen/Ablegen nicht richtig properly

HTML5 DnD - Warum funktioniert das Geisterbild nur nach dem Ziehen und Ablegen eines Elements wie erwartet?

Das Ziehen von JavaScript-Elementen funktioniert nicht

Tippen Sie auf Ziehen und Ablegen auf das Ziel

Deaktivieren Sie das Ziehen und Ablegen des ausgewählten Texts

Wie kann ich das Ziehen und Ablegen von Dateien mit einer Fensterüberlagerung und mehreren Ablagezonen handhaben?

Das Senden von Rohdaten in Scapy funktioniert nicht ordnungsgemäß

Das Hinzufügen von Produkten zum Warenkorb funktioniert nicht ordnungsgemäß

TOP Liste

  1. 1

    Wie aktualisiere ich ein Feld in einer Raumdatenbank mit einem Repository und einem Ansichtsmodell?

  2. 2

    Wie füge ich mehrere Spalten in einer Spalte mit derselben Tabelle in SQL Server zusammen?

  3. 3

    Wie kann man Gitterquadrate dazu bringen, die Farbe zu ändern?

  4. 4

    Ich kann nicht verstehen, wie man Go-Code in mehreren Dateien kompiliert

  5. 5

    Zählen Sie die Vorkommen jedes Werts in einem Tupel in Python

  6. 6

    Gibt es eine sauberere Möglichkeit, Konstruktorargumente und Instanzeigenschaften einer Klasse in Typescript zu definieren?

  7. 7

    So implementieren Sie Pushwoosh mit ionic 2

  8. 8

    Wie wird der Wert im Dropdown-Menü basierend auf den ausgewählten Daten / IDs angezeigt?

  9. 9

    Tomcat - Leiten Sie den alten Kontextstamm zum neuen Kontextstamm um

  10. 10

    Ändern Sie den Knotenpfad in das aktuelle Verzeichnis

  11. 11

    So erstellen Sie ein Array von Objekten aus zwei Arrays von Objekten mit einem gemeinsamen Schlüssel - JavaScript

  12. 12

    Rufen Sie die ID aus der Datagrid-Ansicht ab und zeigen Sie die Daten in Textfeldern einem anderen Formular an

  13. 13

    base js: Wie füge ich einem Objekt eine Eigenschaft auf die 'alte' Weise hinzu?

  14. 14

    Ersetze einen Teil einer Zeichenfolge durch eine Pandas-Spalte als Muster

  15. 15

    Blättern Sie auf Radio Click zur Abschnitts-ID

  16. 16

    CBCentralManager wird nach dem Verbinden neu gestartet

  17. 17

    Scherz, wie man eine Funktion verspottet, die von einer verspotteten Funktion zurückgegeben wird

  18. 18

    django-allauth Empfängersignal zum Hinzufügen einer Gruppenberechtigung zum Benutzer bei der Anmeldung

  19. 19

    Tic Tac Toe-Spiel im React-Reset-Button funktioniert nicht

  20. 20

    AQL: Teilweise Übereinstimmung in einer Reihe von Zeichenfolgen

  21. 21

    So summieren Sie die Werte zweier Tabellen und gruppieren sie nach Datum

heißlabel

Archiv