QWidget в QTreeWidgetItem исчезает после переупорядочения QTreeWidgetItem - PullRequest
0 голосов
/ 19 мая 2018

Я вложил в подкласс QTreeWidget (он называется ToolsSelectorWidget) и включил переупорядочение в нем путем переопределения QTreeWidget :: dropEvent ()

void ToolsSelectorWidget::dropEvent(QDropEvent *event) {
    QModelIndex droppedIndex = indexAt(event->pos());

    if( !droppedIndex.isValid() || droppedIndex.parent().isValid()) {
        return;
    }
   QTreeWidget::dropEvent(event);
}

Также я добавляю QWidgets (QPushButton, QLineEdit) к элементам верхнего уровняQTreeWidget:

ToolsSelectorWidget::ToolsSelectorWidget(QWidget *parent) : QTreeWidget(parent) {
    header()->hide();
    setSelectionMode(QAbstractItemView::SingleSelection);
    setDragEnabled(true);
    viewport()->setAcceptDrops(true);
    setDropIndicatorShown(true);
    setDragDropMode(QAbstractItemView::InternalMove);

    for(int i=0; i<4; ++i) {
        QTreeWidgetItem *part = new QTreeWidgetItem(this);
        part->setFlags(part->flags() & Qt::ItemFlag((~Qt::ItemIsDropEnabled)));
        setItemWidget(part, 0, new QLabel("Part" + QString::number(i) + " Preview", this));
        setItemWidget(part, 1, new QLineEdit("Part" + QString::number(i) + " Name", this));
        setItemWidget(part, 2, new QCheckBox("Part" + QString::number(i) + " Visible", this));
        setItemWidget(part, 3, new QCheckBox("Part" + QString::number(i) + " Locked", this));

    }
}

Так что теперь у меня есть 4 элемента верхнего уровня, каждый из которых содержит 4 QWidget.Он заполняет их нормально, но когда я переставляю их перетаскиванием, QWidgets исчезают, и у меня получается пустой ряд.Что я должен сделать, чтобы сохранить их?

До:

enter image description here

После того, как часть 2 была перемещена и находится под частью 4, у нее есть детибыли сохранены, но его компоненты, которые являются QWidgets, исчезли:

enter image description here

1 Ответ

0 голосов
/ 21 мая 2018

Почему виджеты удаляются?

Когда выполняется перетаскивание, данные выбранных элементов кодируются (роли и связанные значения) и сохраняются в QMimeData.Когда отбрасывание принято, исходные элементы удаляются, и создаются новые элементы с информацией, хранящейся в QMimeData, внутри сохраненной информации нет информации о виджетах, поскольку она не имеет отношения к модели.И поскольку элементы удаляются, их виджеты также удаляются.

Чтобы проверить это, мы можем использовать следующий пример

#include <QApplication>
#include <QLabel>
#include <QTreeWidget>
#include <QDebug>

static void on_destroyed(){
    qDebug()<<"destroyed";
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTreeWidget w;
    w.setSelectionMode(QAbstractItemView::SingleSelection);
    w.setDragEnabled(true);
    w.viewport()->setAcceptDrops(true);
    w.setDropIndicatorShown(true);
    w.setDragDropMode(QAbstractItemView::InternalMove);

    for(int i=0; i< 5; i++){
        QTreeWidgetItem *it = new QTreeWidgetItem(&w);
        QLabel *lbl = new QLabel(QString::number(i));
        QObject::connect(lbl, &QObject::destroyed, on_destroyed);
        w.setItemWidget(it, 0, lbl);
    }
    w.show();
    return a.exec();
}

Это показывает, что виджеты будут излучать сигнал, который они разрушают, когда выперетащите элементы.

Возможное решение:

Одним из возможных решений является удаление виджетов перед принятием удаления и установка их в новых элементах, которые я не реализовал.

Я исследовал другое решение, это изменить QTreeWidget на QTreeView + QStandardItemModel.В случае QCheckBox флажки с флагом Qt::ItemIsUserCheckable включены, в случае QLineEdit будет использоваться делегат, и для постоянного отображения должен использоваться метод openPersistentEditor().

#include <QApplication>
#include <QStandardItemModel>
#include <QTreeView>
#include <QHeaderView>
#include <QDropEvent>
#include <QStyledItemDelegate>
#include <QLineEdit>

class ToolsSelectorDelegate: public QStyledItemDelegate{
public:
    using QStyledItemDelegate::QStyledItemDelegate;
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const{
        QLineEdit *le = new QLineEdit(parent);
        return le;
    }
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const{
        QRect r(option.rect);
        r.adjust(2, 2, -2, -2);
        editor->setGeometry(r);
    }
};

class ToolsSelectorWidget: public QTreeView{
    QStandardItemModel model;
public:
    ToolsSelectorWidget(QWidget *parent=nullptr): QTreeView(parent){
        setItemDelegate(new ToolsSelectorDelegate(this));
        setModel(&model);
        header()->hide();
        setSelectionMode(QAbstractItemView::SingleSelection);
        setDragEnabled(true);
        viewport()->setAcceptDrops(true);
        setDropIndicatorShown(true);
        setDragDropMode(QAbstractItemView::InternalMove);

        for(int i=0; i<4; ++i) {
            QList<QStandardItem *> items;
            for(const QString & text: {"Preview", "Name", "Visible", "Locked"}){
                QStandardItem *it = new QStandardItem(QString("Part%1 %2").arg(i).arg(text));
                it->setFlags(it->flags() & ~Qt::ItemIsDropEnabled & ~Qt::ItemIsEditable);
                items.append(it);
                if(text == "Visible" || text == "Locked"){
                    it->setFlags(it->flags() | Qt::ItemIsUserCheckable);
                    it->setCheckState(Qt::Unchecked);
                }
                else if (text == "Name") {
                    it->setFlags(it->flags() | Qt::ItemIsEditable);
                }
            }
            for(const QString & children: {"The", "quick", "Brown", "fox", "jump...", "over", "the", "lazy", "dog"})
                items.first()->appendRow(new QStandardItem(children));

            model.invisibleRootItem()->appendRow(items);
            for( int i = 0; i < model.rowCount(); ++i )
                openPersistentEditor(model.index(i, 1));
        }
    }
protected:
    void dropEvent(QDropEvent *event) {
        QModelIndex droppedIndex = indexAt(event->pos());
        if( !droppedIndex.isValid() || droppedIndex.parent().isValid())
            return;
        QTreeView::dropEvent(event);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ToolsSelectorWidget w;
    w.show();
    return a.exec();
}
...