如何将参数传递给 QStyledItemDelegate 的 createEditor 函数
How to pass a parameter to createEditor functions of QStyledItemDelegate
一个软件工具有一个 table 填充了两列:参数和数据。 “数据”列有组合框小部件。如何将 listData
作为参数传递给 createEditor
函数,我可以将 listCombo
分配给 listData
?
import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
import pandas as pd
class DataDelegate(QStyledItemDelegate):
def createEditor(self, parent, opt, index):
comboBox = QComboBox(parent)
listCombo = []
comboBox.addItems(listCombo)
comboBox.setCurrentIndex(1)
comboBox.currentTextChanged.connect(lambda: self.commitData.emit(comboBox))
return comboBox
class Window(QWidget):
singleton: 'Window' = None
def __init__(self):
super(Window, self).__init__()
self.setWindowTitle("Software tool")
self.setGeometry(50, 50, 1800, 900)
self.mainLayout=QHBoxLayout()
self.setLayout(self.mainLayout)
self.UI()
self.table.itemChanged.connect(self._print)
def UI(self):
self.sublayouts = {}
self.buttons = {}
self._view()
self._fillTableWidget()
self.show()
def _view(self):
self.table = QTableWidget(0, 2)
self.table.setHorizontalHeaderLabels(['Parameter', 'Data'])
self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
self.table.setEditTriggers(QTableWidget.NoEditTriggers)
self.sublayouts['table'] = QGridLayout()
self.sublayouts['table'].addWidget(self.table, 1, 0, 4, 4)
self.sublayouts['table'].setRowStretch(4, 1)
self.mainLayout.addLayout(self.sublayouts['table'])
self.table.setItemDelegateForColumn(1, DataDelegate(self.table))
def _fillTableWidget(self):
listCol = {
'Parameters': ['a', 'b', 'c', 'd', 'e'],
'Data': ['data1', 'data2', 'data3', 'data4', 'data5']}
self.df = pd.DataFrame(listCol)
listData = self.df['Data'].to_list()
print(listData)
for parameter in self.df['Parameters']:
rowPosition = self.table.rowCount()
self.table.insertRow(rowPosition)
self.table.setItem(rowPosition, 0, QTableWidgetItem(parameter))
dataItem = QTableWidgetItem()
self.table.setItem(rowPosition, 1, dataItem)
self.table.openPersistentEditor(self.table.item(rowPosition, 1))
def _tableCell(self, text):
item = QTableWidgetItem()
item.setText(text)
return item
def _print(self):
print('Item changed:')
def main():
App=QApplication(sys.argv)
window =Window()
sys.exit(App.exec_())
if __name__ == '__main__':
main()
一个可能的解决方案是将默认列表设置为委托的 instance 属性,在 createEditor()
中使用该列表并在检索模型时覆盖它:
class DataDelegate(QStyledItemDelegate):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.items = []
def setItems(self, items):
self.items[:] = items
def createEditor(self, parent, opt, index):
comboBox = QComboBox(parent)
comboBox.addItems(self.items)
comboBox.setCurrentIndex(1)
comboBox.currentTextChanged.connect(
lambda: self.commitData.emit(comboBox))
return comboBox
class Window(QWidget):
# ...
def _view(self):
# ...
self.dataDelegate = DataDelegate(self.table)
self.table.setItemDelegateForColumn(1, self.dataDelegate)
def _fillTableWidget(self):
listCol = {
'Parameters': ['a', 'b', 'c', 'd', 'e'],
'Data': ['data1', 'data2', 'data3', 'data4', 'data5']}
self.df = pd.DataFrame(listCol)
listData = self.df['Data'].to_list()
self.dataDelegate.setItems(listData)
# ...
注意:currentTextChanged
信号应该在您 实际上 需要它时使用(这通常是可编辑组合框所必需的,并且在某些情况下可能不会触发) ;虽然即使在不同的项目中存在相同的文本时,通常也会为不可编辑的组合框发出该信号,但这种行为 可能 在未来发生变化,并且 currentIndexChanged
通常是首选,尤其是对于模型编辑器,因为数据应该只在编辑器实际提交时更新。
一个软件工具有一个 table 填充了两列:参数和数据。 “数据”列有组合框小部件。如何将 listData
作为参数传递给 createEditor
函数,我可以将 listCombo
分配给 listData
?
import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
import pandas as pd
class DataDelegate(QStyledItemDelegate):
def createEditor(self, parent, opt, index):
comboBox = QComboBox(parent)
listCombo = []
comboBox.addItems(listCombo)
comboBox.setCurrentIndex(1)
comboBox.currentTextChanged.connect(lambda: self.commitData.emit(comboBox))
return comboBox
class Window(QWidget):
singleton: 'Window' = None
def __init__(self):
super(Window, self).__init__()
self.setWindowTitle("Software tool")
self.setGeometry(50, 50, 1800, 900)
self.mainLayout=QHBoxLayout()
self.setLayout(self.mainLayout)
self.UI()
self.table.itemChanged.connect(self._print)
def UI(self):
self.sublayouts = {}
self.buttons = {}
self._view()
self._fillTableWidget()
self.show()
def _view(self):
self.table = QTableWidget(0, 2)
self.table.setHorizontalHeaderLabels(['Parameter', 'Data'])
self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
self.table.setEditTriggers(QTableWidget.NoEditTriggers)
self.sublayouts['table'] = QGridLayout()
self.sublayouts['table'].addWidget(self.table, 1, 0, 4, 4)
self.sublayouts['table'].setRowStretch(4, 1)
self.mainLayout.addLayout(self.sublayouts['table'])
self.table.setItemDelegateForColumn(1, DataDelegate(self.table))
def _fillTableWidget(self):
listCol = {
'Parameters': ['a', 'b', 'c', 'd', 'e'],
'Data': ['data1', 'data2', 'data3', 'data4', 'data5']}
self.df = pd.DataFrame(listCol)
listData = self.df['Data'].to_list()
print(listData)
for parameter in self.df['Parameters']:
rowPosition = self.table.rowCount()
self.table.insertRow(rowPosition)
self.table.setItem(rowPosition, 0, QTableWidgetItem(parameter))
dataItem = QTableWidgetItem()
self.table.setItem(rowPosition, 1, dataItem)
self.table.openPersistentEditor(self.table.item(rowPosition, 1))
def _tableCell(self, text):
item = QTableWidgetItem()
item.setText(text)
return item
def _print(self):
print('Item changed:')
def main():
App=QApplication(sys.argv)
window =Window()
sys.exit(App.exec_())
if __name__ == '__main__':
main()
一个可能的解决方案是将默认列表设置为委托的 instance 属性,在 createEditor()
中使用该列表并在检索模型时覆盖它:
class DataDelegate(QStyledItemDelegate):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.items = []
def setItems(self, items):
self.items[:] = items
def createEditor(self, parent, opt, index):
comboBox = QComboBox(parent)
comboBox.addItems(self.items)
comboBox.setCurrentIndex(1)
comboBox.currentTextChanged.connect(
lambda: self.commitData.emit(comboBox))
return comboBox
class Window(QWidget):
# ...
def _view(self):
# ...
self.dataDelegate = DataDelegate(self.table)
self.table.setItemDelegateForColumn(1, self.dataDelegate)
def _fillTableWidget(self):
listCol = {
'Parameters': ['a', 'b', 'c', 'd', 'e'],
'Data': ['data1', 'data2', 'data3', 'data4', 'data5']}
self.df = pd.DataFrame(listCol)
listData = self.df['Data'].to_list()
self.dataDelegate.setItems(listData)
# ...
注意:currentTextChanged
信号应该在您 实际上 需要它时使用(这通常是可编辑组合框所必需的,并且在某些情况下可能不会触发) ;虽然即使在不同的项目中存在相同的文本时,通常也会为不可编辑的组合框发出该信号,但这种行为 可能 在未来发生变化,并且 currentIndexChanged
通常是首选,尤其是对于模型编辑器,因为数据应该只在编辑器实际提交时更新。