我的问题是我有两个QTreeWidgets,我想从一个拖放到另一个(反之亦然)。我可以拖放QTreeWidgetItems,但是,当我删除一个有子节点的QTreeWidgetItem时,我丢失了它们,只丢弃了父节点。
我真的不知道该怎么做。我找到的唯一方法是重新实现dropEvent并销毁所有丢弃的对象并重新构建它们。但是我不喜欢这个解决方案,因为它很慢并且对象不一样,所以它非常复杂撤消/重做功能的实现...
嗯,这就是我所拥有的:
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QWidget>
#include <QString>
#include <QTextStream>
#include <QIODevice>
#include <QMainWindow>
#include <QVBoxLayout>
#include "KTreeWidget.h"
#include "KAbstractItem.h"
#include "KItem.h"
#include "KItemGroup.h"
int main(int argc, char* argv[]){
QApplication app(argc, argv);
QMainWindow *window = new QMainWindow();
QWidget* central = new QWidget(window);
QVBoxLayout *layout = new QVBoxLayout();
KTreeWidget* kv = new KTreeWidget(window);
KTreeWidget* trash = new KTreeWidget(window);
layout->addWidget(kv);
layout->addWidget(trash);
central->setLayout(layout);
KItem* kiarr[5];
for (int i = 0 ; i < 5 ; i++){
kiarr[i] = new KItem(kv);
kiarr[i]->setText(0,QString("Item %1").arg(i));
}
KItemGroup* kgarr[5];
for (int i = 0 ; i < 5 ; i++){
kgarr[i] = new KItemGroup(trash);
kgarr[i]->setText(0,QString("Group %1").arg(i));
}
window->setCentralWidget(central);
window->show();
return app.exec();
}
我的QTreeWidget: KtreeWidget.h
#ifndef _KTW_H_
#define _KTW_H_
#include <QTreeWidget>
class KTreeWidget: public QTreeWidget{
Q_OBJECT
private:
QTreeWidgetItem* _header;
public:
KTreeWidget(QWidget* w = NULL);
};
#endif
和KTreeWidget.cc:
#include "KTreeWidget.h"
KTreeWidget::KTreeWidget(QWidget* w):QTreeWidget(w){
setColumnCount(3);
_header = new QTreeWidgetItem(NULL);
_header->setText(0,"Title");
_header->setText(1,"Edit");
_header->setText(2,"Open");
this->setDefaultDropAction(Qt::MoveAction);
setHeaderItem(_header);
setDragEnabled(true);
setAcceptDrops(true);
}
和项目(3个类,以区分组和叶子): KAbstractItem.h
#ifndef _KABSI_H_
#define _KABSI_H_
#include <QObject>
#include <QTreeWidgetItem>
#include <QTreeWidget>
class KAbstractItem : public QObject, public QTreeWidgetItem{
Q_OBJECT
public:
KAbstractItem(QTreeWidget* p = NULL);
};
#endif
和KAbstractItem.cc
#include "KAbstractItem.h"
KAbstractItem::KAbstractItem(QTreeWidget* p):QTreeWidgetItem(p){}
KItem.h
#ifndef _KI_H_
#define _KI_H_
#include "KAbstractItem.h"
class KItem : public KAbstractItem{
Q_OBJECT
public:
KItem(QTreeWidget* p);
};
#endif
和KItem.cc
#include "KItem.h"
KItem::KItem(QTreeWidget* p):KAbstractItem(p){
setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEditable
| Qt::ItemIsDragEnabled
| Qt::ItemIsUserCheckable
| Qt::ItemIsEnabled);
}
和KItemGroup.h
#ifndef _KIG_H_
#define _KIG_H_
#include "KAbstractItem.h"
class KItemGroup : public KAbstractItem{
Q_OBJECT
public:
KItemGroup(QTreeWidget* p);
};
#endif
和KItemGroup.h #include&#34; KItemGroup.h&#34;
KItemGroup::KItemGroup(QTreeWidget* p):KAbstractItem(p){
setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEditable
| Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled
| Qt::ItemIsUserCheckable
| Qt::ItemIsEnabled);
}
每当我在第一个WTreeWifget中的一个项目中删除第二个组中的一个组时,它就可以了,但是然后我将一个组移到顶部QTreeWidget,我失去了所有的孩子......
你告诉我我做错了吗? 提前谢谢!答案 0 :(得分:1)
所以,我检查过它并没有按要求工作,你没有做错任何事。
我似乎问题是QAbstractItemModel(在QTreeWidget relies中对内部拖动的数据进行编码)mimeData()方法is not considering nested items(它只是编码行+列,但不是父
甚至可能是视图只是将拖动项的QModelIndex传递给mimeData,想想,它可能会更好,因为不考虑父信息...
我看到的唯一解决方案是重新实现dropevent。但你不必破坏这些物品。 使用
QTreeWidgetItem * QTreeWidgetItem::takeChild ( int index ) QTreeWidgetItem * QTreeWidget::takeTopLevelItem ( int index )
采取拖动的项目
和
void QTreeWidgetItem::insertChild ( int index, QTreeWidgetItem * child )
放弃它
我已经检查过这种方式,孩子们是正确的。 (见this gist)
答案 1 :(得分:0)
这是我解决它的方式: 当您拖放时,At创建一个新对象,与您的文本相同的值不同,但是它是另一个对象,只是删除了你的对象,但是没有释放内存。
要做的第一件事就是覆盖removeChild,因为它基于索引而不是地址,所以它不能很好地用于我们将要做的事情。 (http://sourceforge.net/p/ckmapper/code/4/tree/trunk/src/KViewer/KAbstractItem.cc#l39)
然后我们需要做的是覆盖QTreeWidget的dropEvent。战术如下:
我们必须重写removeChild,因为WE正在手动删除子项(所选项目),而Qt正在删除它应该删除的项目(也不是选定的项目)(但它没有)。因此,如果您检查Qt代码,您将看到它基于索引,这不安全,而根据其地址删除项目更安全。 我会在这里发布我的代码,我忘了提交它;)
无论如何,Trompa的解决方案也是有效的,对我来说似乎更简单。我也想分享我的解决方案;)