如果更改单元格值则调用一个函数 - 对于 table 中旋转框的动态数量
Call a function if cell value is changed - for dynamic number of spinBoxes in a table
我正在编写一个软件工具,其中 table 填充了两列:参数和精度。 “Precision”列中的一些参数具有 spinBox 小部件,而一些参数只有文本“N/A”。旋转框的数量是动态的。如果带有旋转框的单元格的值发生变化,如何调用函数?
我尝试用 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()
, and also connects the spin box valueChanged
signal to the delegate's commitData()
的自定义 QSpinBox,它实际上会在模型上设置数据。
通过这种方式,您不仅可以连接到 table 的 itemChanged
以接收有关数据更改的通知,而且您还可以 直接 访问 table 数据(这在您的情况下不起作用,因为数据未设置并且仅在旋转框中可用)。
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))
我正在编写一个软件工具,其中 table 填充了两列:参数和精度。 “Precision”列中的一些参数具有 spinBox 小部件,而一些参数只有文本“N/A”。旋转框的数量是动态的。如果带有旋转框的单元格的值发生变化,如何调用函数?
我尝试用 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()
, and also connects the spin box valueChanged
signal to the delegate's commitData()
的自定义 QSpinBox,它实际上会在模型上设置数据。
通过这种方式,您不仅可以连接到 table 的 itemChanged
以接收有关数据更改的通知,而且您还可以 直接 访问 table 数据(这在您的情况下不起作用,因为数据未设置并且仅在旋转框中可用)。
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))