QListWidget拖拽至原位置丢失行内容的修复方案咨询
QListWidget InternalMove拖拽到原位置丢失内容的修复方案
问题描述
使用PySide2开发时,将QListWidget的拖拽模式设置为QAbstractItemView.InternalMove后,会出现异常:当把某一行拖拽到其原位置时,该行的自定义控件内容会丢失,变为空条目。
复现步骤
- 拖拽第一行“textt 0”到原位置
- 第一行文本消失,变为空条目
修复思路
问题根源在于QListWidget默认的内部拖拽逻辑中,当检测到拖拽操作到原位置时,会触发item重置,但通过setItemWidget绑定的自定义控件不会被自动保留。我们可以通过重写dropEvent方法,判断拖拽目标是否为原位置,直接忽略该操作来避免内容丢失。
修复代码
import sys from PySide2.QtWidgets import QWidget, QLabel, QApplication, QVBoxLayout, QListWidget, QListWidgetItem, QAbstractItemView class FixedListWidget(QListWidget): def dropEvent(self, event): source_item = self.currentItem() if not source_item: super().dropEvent(event) return # 获取拖拽落点对应的item target_item = self.itemAt(event.pos()) # 若拖拽到原位置,直接忽略事件 if target_item == source_item: event.ignore() return # 其他情况执行默认拖拽逻辑 super().dropEvent(event) class main(QWidget): def __init__(self): super().__init__() self.setStyleSheet('*{font-size:25px;}') self.layout = QVBoxLayout() table = FixedListWidget() table.setDragDropMode(QAbstractItemView.InternalMove) for i in range(5): item = QListWidgetItem() widget = QLabel(f'textt {i}') table.addItem(item) table.setItemWidget(item, widget) self.layout.addWidget(table) self.setLayout(self.layout) class app(QApplication): def __init__(self): super().__init__(sys.argv) self.main = main() self.main.show() if __name__ == "__main__": app = app() sys.exit(app.exec_())
代码说明
- 自定义
FixedListWidget类,重写dropEvent方法:- 获取当前拖拽的源item和落点对应的目标item
- 当目标item和源item为同一个时,调用
event.ignore()跳过默认处理,避免内容丢失
- 修正原代码中
QApplication初始化时缺少sys.argv的问题,确保程序正常启动
内容的提问来源于stack exchange,提问作者math4end
相关产品推荐
相关产品推荐

