1. 解决无法拖入文件到QListWidget

一般而言,只需要做如下操作,QWidget即可支持拖入文件:

1
2
3
4
5
6
7
8
setDragDropMode(QAbstractItemView::DropOnly); // 仅支持拖入文件


// 重写dragEnterEvent,当拖入文件进入时被调用,可以在该函数中取消拖入操作
void dragEnterEvent(QDragEnterEvent* e) override;

// 重写dropEvent,当拖入文件并释放鼠标时被调用
void dropEvent(QDropEvent* e) override;

但在执行上述操作后,我们拖入文件到QListWidget时,却只能收到dragEnterEvent事件,却无法收到dropEvent事件。

因为还需要重写dragMoveEvent方法,如:

1
2
3
void dragMoveEvent(QDragMoveEvent* e) {
e->acceptProposedAction();
}

2. QListWidgetItem自适应尺寸

QListWidget添加item的方法如下:

1
2
3
4
5
6
QListWidget* list = new QListWidget();

// ...

QListWidgetItem* item = new QListWidgetItem();
list->addItem(item);

如需要自定义Item的布局,还可以通过自定义Widget来实现,如:

1
2
3
4
5
6
7
8
9
QListWidget* list = new QListWidget();

// ...

QListWidgetItem* item = new QListWidgetItem();
list->addItem(item);

CustomWidget * customWidget = new CustomWidget();
list->setItemWidget(item, customWidget); // 设置Item的自定义Widget

此时,我们还没有为item设置size hint,item会自动根据item的数据(如text)计算size hint。但如果是自定义的Widget,则无法自动计算size hint,需要手动设置size hint,如:

1
2
3
4
5
6
int vScrollbarWidth = 0;
if (verticalScrollBar())
vScrollbarWidth = verticalScrollBar()->width();

// 减去纵坐标的宽度
item->setSizeHint(QSize(list->width() - vScrollbarWidth, widget->height()));

QListWidget的滚动条默认显示策略是ScrollBarAsNeeded,当宽度不够显示Item时,滚动条就会显示出来,此时虽然QListWidget宽度改变了,但Item的宽度却不会改变,Item不会收到ResizeEvent事件。如需Item的宽度跟随QListWidget宽度而改变,则需要关闭滚动条显示,并在 QListWidget 的 ResizeEvent 事件中实时设置每个Item的size hint,代码如下:

1
2
// 关闭滚动条
list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void FileList::resizeEvent(QResizeEvent* e) {
int vScrollbarWidth = 0;
if (verticalScrollBar())
vScrollbarWidth = verticalScrollBar()->width();

int w = width();
int cnt = count();
for (int i = 0; i < cnt; i++) {
QListWidgetItem* it = item(i);
if (it) {
CustomWidget* customWidget = dynamic_cast<CustomWidget*>(itemWidget(it));
if (customWidget) {
it->setSizeHint(QSize(w - vScrollbarWidth, customWidget->height()));
}
}
}
QListWidget::resizeEvent(e);
}