python - PyQt5 QListView 拖放创建新的隐藏项
问题描述
我有一个 PyQt5 QListview,其中包含一个项目列表,可以通过拖放重新排列并选中一个复选框。问题是当我重新排列列表中的项目时,项目在 GUI 中重新排列正确,但是当我尝试保存输出时,移动项目的原始位置和新位置都有一个副本。
创建列表的函数
def create_methods_list(self):
self.methods_list = QListView()
self.methods_list.setDragDropMode(QListView.InternalMove)
self.methods_list.setDefaultDropAction(Qt.MoveAction)
self.methods_list.setDragDropMode(False)
self.methods_list.setAcceptDrops(True)
self.methods_list.setDropIndicatorShown(True)
self.methods_list.setDragEnabled(True)
self.methods_list.setWindowTitle('Method Order')
self.methods_model = QtGui.QStandardItemModel(self.methods_list)
# self.methods is a list of strings
for method in self.methods:
item = QtGui.QStandardItem(method)
item.setData(method)
item.setCheckable(True)
item.setDragEnabled(True)
item.setDropEnabled(False)
item.setCheckState(True)
self.methods_model.appendRow(item)
self.methods_model.itemChanged.connect(self.method_item_changed)
self.methods_list.setModel(self.methods_model)
重新排列列表时调用的函数:
def method_item_changed(self):
print(self.methods_model.rowCount())
i = 0
new_methods = []
while self.methods_model.item(i):
if self.methods_model.item(i).checkState():
new_methods.append(self.methods_model.item(i).data())
i += 1
print(new_methods)
self.methods = new_methods
第一个打印语句返回一个比原始列表中的项目数高的一个。第二个打印语句返回列表中的项目,但移动的项目既位于原始位置又位于新位置。
我尝试了一个解决方案,其中包括添加一个间隔很短的 QTimer,但没有奏效。
任何帮助将不胜感激。
完整工作版:
from PyQt5.QtWidgets import (
QAction, QWidget, QLabel, QDesktopWidget,
QApplication, QComboBox, QPushButton, QGridLayout,
QMainWindow, qApp, QVBoxLayout, QSlider,
QHBoxLayout, QLineEdit, QListView, QAbstractItemView
)
from PyQt5.QtCore import Qt
from PyQt5 import QtGui
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.methods = ['option 1', 'option 2', 'option 3']
self.central_widget = QWidget(self)
self.layout = QVBoxLayout(self.central_widget)
self.layout.addStretch()
self.create_methods_list()
self.layout.addWidget(self.methods_list)
self.layout.addStretch()
self.setCentralWidget(self.central_widget)
self.show()
def create_methods_list(self):
self.methods_list = QListView()
self.methods_list.setDragDropMode(QListView.InternalMove)
self.methods_list.setDefaultDropAction(Qt.MoveAction)
self.methods_list.setDragDropMode(False)
self.methods_list.setAcceptDrops(True)
self.methods_list.setDropIndicatorShown(True)
self.methods_list.setDragEnabled(True)
self.methods_list.setWindowTitle('Method Order')
self.methods_model = QtGui.QStandardItemModel(self.methods_list)
for method in self.methods:
item = QtGui.QStandardItem(method)
item.setData(method)
item.setCheckable(True)
item.setDragEnabled(True)
item.setDropEnabled(False)
item.setCheckState(True)
self.methods_model.appendRow(item)
self.methods_model.itemChanged.connect(self.method_item_changed)
self.methods_list.setModel(self.methods_model)
self.methods_list.setMinimumHeight(
self.methods_list.sizeHintForRow(0)
* (self.methods_model.rowCount() + 2))
def method_item_changed(self):
print(self.methods_model.rowCount())
i = 0
new_methods = []
while self.methods_model.item(i):
if self.methods_model.item(i).checkState():
new_methods.append(self.methods_model.item(i).data())
i += 1
self.methods = new_methods
print(self.methods)
if __name__=='__main__':
app = QApplication(sys.argv)
ex = MainWindow()
ex.show()
sys.exit(app.exec_())
解决方案
当一个项目从一个位置移动到另一个i
位置时j
,所做的是:
- 在适当位置插入项目
j
- 将数据复制到新项目,此时
itemChanged
发出信号,因此您会看到有更多的元素 - 删除该位置的项目
i
。
这就是这种行为的原因。但我不明白需要更新该列表。正常的事情是获取需要的检查项,也就是说有一个函数,在必要时调用并计算它。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.methods = ['option 1', 'option 2', 'option 3']
central_widget = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout(central_widget)
self.create_methods_list()
layout.addWidget(self.methods_list)
layout.addStretch()
self.setCentralWidget(central_widget)
def create_methods_list(self):
self.methods_list = QtWidgets.QListView()
self.methods_list.setDragDropMode(QtWidgets.QListView.InternalMove)
self.methods_list.setDefaultDropAction(QtCore.Qt.MoveAction)
self.methods_list.setAcceptDrops(True)
self.methods_list.setDropIndicatorShown(True)
self.methods_list.setDragEnabled(True)
self.methods_model = QtGui.QStandardItemModel(self.methods_list)
for method in self.methods:
item = QtGui.QStandardItem(method)
item.setData(method)
item.setCheckable(True)
item.setDragEnabled(True)
item.setDropEnabled(False)
item.setCheckState(QtCore.Qt.Checked)
self.methods_model.appendRow(item)
self.methods_list.setModel(self.methods_model)
self.methods_list.setMinimumHeight(
self.methods_list.sizeHintForRow(0)
* (self.methods_model.rowCount() + 2))
def get_items_Checked(self):
checkeds = []
for i in range(self.methods_model.rowCount()):
it = self.methods_model.item(i)
if it is not None and it.checkState() == QtCore.Qt.Checked:
checkeds.append(it.text())
return checkeds
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
ex = MainWindow()
ex.show()
sys.exit(app.exec_())
推荐阅读
- python - 如何将堆叠的数据框转换为熊猫中的字典?
- javascript - 更新到 SVG 2 时 SVG 元素损坏,为什么?
- xamarin - 如何在 C# 中获取 quickwatch 表达式值?
- node.js - 如何使用nodejs获取Mongodb查询集中每一列的唯一值
- c# - 如何将stackalloc内存复制到数组中?
- hadoop-yarn - 如何在将 Flink 作业提交到 Yarn 使用命令行界面时获取应用程序 ID?
- node.js - 在heroku中集成Angular SPA和mongodb的问题
- swift - `带有协议副本的概述初始化`是什么意思?
- soap - 如何从 SOAP WS 中的 url 访问查询参数?
- haskell - Haskell-如何将函数的返回值存储到变量中?