【发布时间】:2022-11-01 11:14:56
【问题描述】:
我有一个QListWidget,它由QLabel 通过.setItemWidget() 和一个拖放模式InternalMove 填充,当我在列表中移动一个项目时,它的标签会消失。
我该如何解决这个问题?
重现的最小示例
from PyQt5.QtWidgets import (
QApplication, QLabel, QStyle,
QListWidget, QListWidgetItem
)
from PyQt5.QtCore import QSize
import sys
if __name__ == '__main__':
app = QApplication(sys.argv)
list = QListWidget()
list.setFixedHeight(400)
list.setDragDropMode(QListWidget.DragDropMode.InternalMove)
for _ in range(8):
item = QListWidgetItem()
item.setSizeHint(QSize(40, 40))
list.addItem(item)
label = QLabel()
label.setPixmap(list.style().standardIcon(
QStyle.StandardPixmap.SP_ArrowUp).pixmap(QSize(40,40)))
list.setItemWidget(item, label)
list.show()
sys.exit(app.exec())
【问题讨论】:
-
我在过去看到过这种行为as partially reported in this question,但我从来没有能够始终如一地重现它:大多数时候它都有效,但是有时它做你所展示的。值得注意的是,如果您尝试调整窗口大小,小部件会再次出现,因此索引小部件的几何形状似乎存在问题。也许在 dropEvent 覆盖上强制延迟
updateGeometries可能会有所帮助,但我不太确定,因为如前所述,我只能完全随机地重现它。 -
@musicamante 对我来说,如果我将最后一个项目拖放到
QListWidget的空白区域,如我发布的图片所示,我一直在挖掘它,因为我已经发布了它似乎小部件只在从QListWidget的模型中删除一行,基本上是在QListWidget.model().rowsRemoved被释放时。 -
但这不应该是你的情况,因为索引没有被删除,而只是被移动: QListWidget 在内部通过调用
beginMoveRows()和相关函数开始,所以小部件是与它一起移动,它只是没有正确更新。由于您始终能够重现问题,我们可以尝试了解问题出在哪里:首先创建一个打印所有项目小部件的几何形状的函数,并在移动行时使用延迟的 QTimer 调用它:list.model().rowsMoved.connect(lambda: QTimer.singleShot(100, somefunc))。 -
该函数可能只是一个简单的
for i in range(list.count()):print(list.itemWidget(list.item(i)).geometry())。这显然是基于您上面的示例,为所有项目设置了一个小部件。查看几何图形是否一致(尤其是最后一个,即已移至末尾的项目):尺寸应全部相同,而 y 坐标应始终为先前高度的总和。如果是,则将上面的函数更改为检查可见性的函数 (list.itemWidget(list.item(i)).isVisible())。如果没有,请在您的问题中发布输出。 -
@musicamante 这就是问题所在,当我在已移动的
item上调用itemWidget()时,结果是None基本上item本身仍在列表中,但widget设置为setItemWidget()得到解耦。
标签: python-3.x pyqt5 drag-and-drop qt5 qlistwidget