QListWidget 通过 setItemWidget 拖放自定义小部件集
QListWidget drag and drop with a custom widget set via setItemWidget
我使用 QListWidget 来显示自定义小部件,方法是使用 setItemWidget 进行设置。像这样:
QListWidget* listWidget = new QListWidget;
listWidget->setAcceptDrops(true);
listWidget->setDragDropMode(QAbstractItemView::InternalMove);
listWidget->setDragEnabled(true);
listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
for ( int i = 0 ; i < 50 ; ++i )
{
ItemWidget* item = new ItemWidget;
QListWidgetItem* listItem = new QListWidgetItem;
listItem->setSizeHint(item->sizeHint());
listWidget->addItem(listItem);
listWidget->setItemWidget(listItem, item);
}
ItemWidget 是从QWidget 派生出来的,只是在布局中显示一些自定义数据,像这样:
ItemWidget::ItemWidget()
{
QVBoxLayout* layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
QHBoxLayout* contentLayout = new QHBoxLayout;
contentLayout->setSizeConstraint(QLayout::SetFixedSize);
contentLayout->setSpacing(0);
contentLayout->addSpacing(5);
contentLayout->setContentsMargins(10, 20, 10, 20);
QLabel* iconLbl = new QLabel;
iconLbl->setPixmap(QPixmap(":/icon.png"));
iconLbl->setMaximumWidth(20);
contentLayout->addWidget(iconLbl, 0, Qt::AlignTop);
contentLayout->addSpacing(14);
QVBoxLayout* infoLayout = new QVBoxLayout;
infoLayout->setContentsMargins(0, 0, 0, 0);
infoLayout->setSpacing(0);
QLabel* firstLbl = new QLabel("First line of text");
infoLayout->addWidget(firstLbl);
infoLayout->addSpacing(4);
QLabel* secondLbl = new QLabel("Second line of text");
infoLayout->addWidget(secondLbl);
contentLayout->addLayout(infoLayout);
layout->addLayout(contentLayout);
setLayout(layout);
}
我想实现拖放以便能够重新排列列表中的项目。但是,当使用 setItemWidget 时,当鼠标拖动项目时,只会拖动背景矩形(QListWidgetItem ?),并显示作为 ItemWidget 一部分的自定义内容的 none。我希望被拖动的项目也包含 ItemWidget 内容,以便用户看到被拖放的内容。
有没有人有实现这个的工作方法?
我已经尝试使用派生自 QListWidgetItem 和 QWidget 的自定义 class,并直接在 class 中设置自定义布局,因此可能不需要 ItemWidget 或使用 setItemWidget,但是结果没有如我所愿。
要自定义与 QListWidget
的 QDrag
关联的 QPixmap
,我们必须覆盖 startDrag()
方法。
主要任务是得到一个QPixmap
的元素,为它创建一个QPixmap
大小的viewport()
的可见图像是透明的,然后我们我们使用 QPainter
.
选择的每个项目的 QPixmap
来绘制它们
获取每一项的QPixmap
,使用grab()
方法,表示通过visualRect()
得到的矩形。
#ifndef LISTWIDGET_H
#define LISTWIDGET_H
#include <QListWidget>
#include <QDrag>
#include <QMimeData>
#include <QPainter>
class ListWidget : public QListWidget
{
protected:
void startDrag(Qt::DropActions supportedActions){
QDrag *drag = new QDrag(this);
drag->setMimeData(model()->mimeData(selectedIndexes()));
QPixmap pixmap(viewport()->visibleRegion().boundingRect().size());
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
for(QModelIndex index: selectedIndexes()){
painter.drawPixmap(visualRect(index), viewport()->grab(visualRect(index)));
}
drag->setPixmap(pixmap);
drag->setHotSpot(viewport()->mapFromGlobal(QCursor::pos()));
drag->exec(supportedActions, Qt::MoveAction);
}
};
#endif // LISTWIDGET_H
完整的例子可以在下面找到link
我使用 QListWidget 来显示自定义小部件,方法是使用 setItemWidget 进行设置。像这样:
QListWidget* listWidget = new QListWidget;
listWidget->setAcceptDrops(true);
listWidget->setDragDropMode(QAbstractItemView::InternalMove);
listWidget->setDragEnabled(true);
listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
for ( int i = 0 ; i < 50 ; ++i )
{
ItemWidget* item = new ItemWidget;
QListWidgetItem* listItem = new QListWidgetItem;
listItem->setSizeHint(item->sizeHint());
listWidget->addItem(listItem);
listWidget->setItemWidget(listItem, item);
}
ItemWidget 是从QWidget 派生出来的,只是在布局中显示一些自定义数据,像这样:
ItemWidget::ItemWidget()
{
QVBoxLayout* layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
QHBoxLayout* contentLayout = new QHBoxLayout;
contentLayout->setSizeConstraint(QLayout::SetFixedSize);
contentLayout->setSpacing(0);
contentLayout->addSpacing(5);
contentLayout->setContentsMargins(10, 20, 10, 20);
QLabel* iconLbl = new QLabel;
iconLbl->setPixmap(QPixmap(":/icon.png"));
iconLbl->setMaximumWidth(20);
contentLayout->addWidget(iconLbl, 0, Qt::AlignTop);
contentLayout->addSpacing(14);
QVBoxLayout* infoLayout = new QVBoxLayout;
infoLayout->setContentsMargins(0, 0, 0, 0);
infoLayout->setSpacing(0);
QLabel* firstLbl = new QLabel("First line of text");
infoLayout->addWidget(firstLbl);
infoLayout->addSpacing(4);
QLabel* secondLbl = new QLabel("Second line of text");
infoLayout->addWidget(secondLbl);
contentLayout->addLayout(infoLayout);
layout->addLayout(contentLayout);
setLayout(layout);
}
我想实现拖放以便能够重新排列列表中的项目。但是,当使用 setItemWidget 时,当鼠标拖动项目时,只会拖动背景矩形(QListWidgetItem ?),并显示作为 ItemWidget 一部分的自定义内容的 none。我希望被拖动的项目也包含 ItemWidget 内容,以便用户看到被拖放的内容。
有没有人有实现这个的工作方法?
我已经尝试使用派生自 QListWidgetItem 和 QWidget 的自定义 class,并直接在 class 中设置自定义布局,因此可能不需要 ItemWidget 或使用 setItemWidget,但是结果没有如我所愿。
要自定义与 QListWidget
的 QDrag
关联的 QPixmap
,我们必须覆盖 startDrag()
方法。
主要任务是得到一个QPixmap
的元素,为它创建一个QPixmap
大小的viewport()
的可见图像是透明的,然后我们我们使用 QPainter
.
QPixmap
来绘制它们
获取每一项的QPixmap
,使用grab()
方法,表示通过visualRect()
得到的矩形。
#ifndef LISTWIDGET_H
#define LISTWIDGET_H
#include <QListWidget>
#include <QDrag>
#include <QMimeData>
#include <QPainter>
class ListWidget : public QListWidget
{
protected:
void startDrag(Qt::DropActions supportedActions){
QDrag *drag = new QDrag(this);
drag->setMimeData(model()->mimeData(selectedIndexes()));
QPixmap pixmap(viewport()->visibleRegion().boundingRect().size());
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
for(QModelIndex index: selectedIndexes()){
painter.drawPixmap(visualRect(index), viewport()->grab(visualRect(index)));
}
drag->setPixmap(pixmap);
drag->setHotSpot(viewport()->mapFromGlobal(QCursor::pos()));
drag->exec(supportedActions, Qt::MoveAction);
}
};
#endif // LISTWIDGET_H
完整的例子可以在下面找到link