gpt4 book ai didi

c++ - QTreeWidgetItem 的拖放不能正常工作

转载 作者:行者123 更新时间:2023-12-02 09:58:01 27 4
gpt4 key购买 nike

我对 QTreeWidget 进行了子类化为了重新实现 protected drag 的功能和 drop为了拖放一个QTreeWidget的 parent 和 child .
它几乎可以工作,问题 就是当我尝试拖放 child 或 parent 时,一旦我放下它们,它们就会被删除。
源码可见here以防您需要查看发生了什么。
此外,如果我尝试拖放父级,不幸的是它不会移动,也没有任何 react 。
请看下面对 children 的奇怪效果:
我将 child “Original”拖到“Sample”下,这个过程似乎可以正常工作:
ddrop
删除“原始”后,您可以看到索引似乎在那里,但似乎被部分删除:
ddrop2
我不确定到底发生了什么,为什么 child 似乎没有完全正确地被丢弃,为什么 parent 实际上一动不动。
在最小可验证示例的代码下方:
主窗口.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
主窗口.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);
}
下面是我如何分类 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);
}
}
}
到目前为止我所做的和我尝试过的:
1) 根据官方文档,可以使用 QTreeWidgetItemIterator Class我试图这样做,事实上你可以在下面看到我最初的实现想法,但这并没有真正把我带到任何地方:
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) 在对官方文档进行进一步研究后,我决定应用 QMapIterator Class 来解决问题。我想保留构造函数,因为我最初构造并认为通过 QMap打算以不同的方式重写构造函数,基本上是下面的实现思想,但不想通过那种方式:
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) 经过更多研究,我发现了 this source , 和 this other source这对于实现 QTreeWidget 的子类化很有用(尤其是最后一篇文章)。 .
现在我被困住了,因为我试图弄清楚为什么尽管我尝试了所有的事情,但我还是实现了 90% 的工作应用程序,因此,它缺少什么?
感谢您提供有关如何解决此问题的指导。

最佳答案

我认为复选框正在处理鼠标事件,并且不要让事件通过该项目。要获得所需的行为,您应该删除此部分:

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));
}
}
createItem()功能:
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;
}

关于c++ - QTreeWidgetItem 的拖放不能正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64322036/

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