我有一个继承自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);
答案 0 :(得分:1)
以下示例显示了正在发生的情况。基本上,规则是这样的:
调用setItemWidget
将Item-Widget的所有权转移到QListWidget
实例。因此,QListWidget
有责任销毁已设置的Item-Widget。
现在,QListWidget
没有成员,因此可以撤回已设置的Item-Widget的所有权。唯一的选择是创建一个具有与要删除的Item-Widget相同属性的新Item-Widget。
请注意,Item-Widget ist稍后会在返回事件循环后删除,这是通过在deleteLater()
内部调用takeItem
来完成的。因此,访问label
直到该插槽的末尾都是有效的。
如果您对此行为不满意,仍然可以使用自己的委托切换到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();
}