gpt4 book ai didi

c++ - QTreeWidgetItem 中的 QWidget 在重新排序 QTreeWidgetItem 后消失

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:39:28 25 4
gpt4 key购买 nike

我已将 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

Part2 移动到 Part4 下后,它的子项被保留,但它的内容,即 QWidgets,消失了:

enter image description here

最佳答案

为什么小部件被删除了?

执行拖放时,所选项目的数据被编码(角色和关联值)并保存在 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 的情况下,委托(delegate)将被使用并始终显示,必须使用 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();
}

关于c++ - QTreeWidgetItem 中的 QWidget 在重新排序 QTreeWidgetItem 后消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50419808/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com