gpt4 book ai didi

c++ - 重用与项目关联的小部件时 QListWidget 崩溃

转载 作者:行者123 更新时间:2023-11-30 04:45:54 29 4
gpt4 key购买 nike

我有一个继承自 QWidget 的自定义简单小部件,我将它添加到 QListWidget 中,如下所示:

void MainWindow::AddToWidgetList(const QString &tag, const QString &html)
{
HtmlItem *html_item = new HtmlItem();
html_item->set_tag(tag);
html_item->set_html(html);
connect(html_item, SIGNAL(RemoveIt(uintptr_t)), this, SLOT(on_RmBtn_clicked(uintptr_t)));
QListWidgetItem *list_item = new QListWidgetItem();
html_item->set_list_item(list_item);
list_item->setSizeHint(html_item->sizeHint());
ui->CodeBlocks->addItem(list_item);
ui->CodeBlocks->setItemWidget(list_item, html_item);
}

然后我想在按下按钮时向上移动所选元素

void MainWindow::on_UpArrowBtn_clicked()
{
if (ui->CodeBlocks->count() < 2)
return;
int current_row = ui->CodeBlocks->currentRow();
if (current_row == 0)
return;
HtmlItem *item_widget = (HtmlItem*)ui->CodeBlocks->itemWidget(ui->CodeBlocks->item(current_row));
QListWidgetItem *item = ui->CodeBlocks->takeItem(current_row);
ui->CodeBlocks->insertItem(current_row - 1, item);
ui->CodeBlocks->setItemWidget(item, item_widget);
}

但我在这一行崩溃了:

ui->CodeBlocks->setItemWidget(item, item_widget);

最佳答案

下面的例子展示了正在发生的事情。基本上,规则是这样的:

调用 setItemWidget 将 Item-Widget 的所有权转移到 QListWidget 实例。因此,QListWidget 负责销毁集合 Item-Widget。

现在,QListWidget 没有成员,这允许撤销集合 Item-Widget 的所有权。唯一的选择是创建一个新的 Item-Widget,其属性与即将删除的 Item-Widget 相同。

请注意,Item-Widget 在返回到事件循环后稍后会被删除,这通过在 takeItem 中调用 deleteLater() 来实现。因此,访问 label 直到 slot 结束都是有效的。

如果您对这种行为不满意,您仍然可以使用自己的委托(delegate)切换到 QListView 类。尽管这似乎需要更多工作,但它是更可扩展的方法。

#include <QApplication>
#include <QHBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include <QLabel>
#include <QDebug>

int main(int argc, char** args) {
QApplication app(argc, args);
auto frame = new QFrame;
auto listWidget = new QListWidget;
for (auto iter=0; iter<10; iter++)
{
auto label = new QLabel(QString("Item-%1").arg(iter));
auto item = new QListWidgetItem();
listWidget->addItem(item);
listWidget->setItemWidget(item, label); // listWidget becomes the owner of label
}
auto moveUp = new QPushButton("Move Up");
frame->setLayout(new QHBoxLayout);
frame->layout()->addWidget(listWidget);
frame->layout()->addWidget(moveUp);
frame->show();
QObject::connect(moveUp, &QPushButton::clicked, [&]()
{
auto row = listWidget->currentRow();
auto item=listWidget->currentItem();
if (!item) return;
if (row == 0) return;

auto label = qobject_cast<QLabel*>(listWidget->itemWidget(item));
if (!label) return;

QObject::connect(label, &QLabel::destroyed, []()
{
qDebug() << "Destroyed"; // takeItem calls deleteLater on itemWidget
});
auto myItem=listWidget->takeItem(row);
listWidget->insertItem(row-1,myItem);
listWidget->setItemWidget(item, new QLabel(label->text())); // copy content of itemWidget and create new widget
listWidget->setCurrentRow(row-1);
});
app.exec();
}

关于c++ - 重用与项目关联的小部件时 QListWidget 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57044933/

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