如果单元格值被改变,调用一个函数——对于一个表中spinbox的动态数量



我正在编写一个软件工具,它有一个包含两列的表:参数和精度。"精度"中的一些参数列有spinBox小部件和一些参数只有文本"N/A"。spinbox的数量是动态的。如何调用一个函数,如果细胞的值与spinBoxes改变?

我试着用self.table.currentItemChanged.connect(self._print)做它,但它不完全是我需要的-它只在我改变spinBox值时调用函数,之后改变行选择,而我需要每次spinBox值改变时调用函数。

import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
import pandas as pd
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()
def UI(self):
self.sublayouts = {}
self.buttons = {}
self._view()
self._fillListWidget()
self.table.currentItemChanged.connect(self._print)
self.show()
def _view(self):
self.table = QTableWidget(0, 2)
self.table.setHorizontalHeaderLabels(['Parameter', 'Precision'])
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'])
def _fillListWidget(self):
listCol = {
'Parameters': ['a', 'b', 'c', 'd', 'e'],
'Precision': [-1, -1, 2, 3, 1]}
self.df = pd.DataFrame(listCol)
for row in zip(*self.df.to_dict('list').values()):
itemColumn = QTableWidgetItem(
row[self.df.columns.get_loc("Parameters")])
rowPosition = self.table.rowCount()
self.table.insertRow(rowPosition)
itemTable = self._tableCell(row[self.df.columns.get_loc("Parameters")])
self.table.setItem(rowPosition, 0, itemTable)
df_tmp = self.df[self.df['Parameters'] == row[self.df.columns.get_loc("Parameters")]]
if df_tmp['Precision'].values[0] >= 0:
self.spinBox=QSpinBox()
self.spinBox.setValue(df_tmp['Precision'].values[0])
self.table.setCellWidget(rowPosition, 1, self.spinBox)
else:
itemTable = self._tableCell('N/A')
self.table.setItem(rowPosition, 1, itemTable)
def _tableCell(self, text):
item = QTableWidgetItem()
item.setText(text)
return item
def _readTable(self):
list_Parameters = []
list_Precision = []
print('1')
for i in range(self.table.rowCount()):
print(self.table.item(i, 0).text())
list_Parameters.append(self.table.item(i, 0).text())
list_Precision.append(self.table.item(i, 1).text())
def _print(self):
print('Precision changed')
def main():
App=QApplication(sys.argv)
window =Window()
sys.exit(App.exec_())
if __name__ == '__main__':
main()

不应该设置小部件项,而应该使用Qt.DisplayRole设置索引的值,并打开一个持久编辑器,该编辑器在默认情况下已经是一个用于数值的自旋框。

因为你想要一个专门的行为,你可以使用一个自定义委托,通过返回一个带有createEditor()的自定义QSpinBox来实现它,并且还将自旋盒valueChanged信号连接到委托的commitData(),这将实际设置模型上的数据。

通过这种方式,您不仅可以连接到表的itemChanged以获得有关数据更改的通知,而且还可以直接访问表数据(这在您的情况下是行不通的,因为数据没有设置,只能在自旋框中可用)。

class PrecisionDelegate(QStyledItemDelegate):
def createEditor(self, parent, opt, index):
editor = QSpinBox(parent)
editor.setMinimum(-1)
editor.setSpecialValueText('N/A')
editor.valueChanged.connect(lambda: self.commitData.emit(editor))
return editor

class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.setWindowTitle("Software tool")
self.mainLayout = QHBoxLayout(self)
self.UI()
self.table.itemChanged.connect(self._print)
def _view(self):
# ...
self.table.setItemDelegateForColumn(1, PrecisionDelegate(self.table))
def _fillListWidget(self):
listCol = {
'Parameters': ['a', 'b', 'c', 'd', 'e'],
'Precision': [-1, -1, 2, 3, 1]}
self.df = pd.DataFrame(listCol)
for parameter, precision in zip(self.df['Parameters'], self.df['Precision']):
rowPosition = self.table.rowCount()
self.table.insertRow(rowPosition)
self.table.setItem(rowPosition, 0, QTableWidgetItem(parameter))
precisionItem = QTableWidgetItem()
precisionItem.setData(QtCore.Qt.DisplayRole, precision)
self.table.setItem(rowPosition, 1, precisionItem)
self.table.openPersistentEditor(self.table.item(rowPosition, 1))

相关内容

最新更新