QTableWidget-自动公式驱动单元格
QTableWidget- automatic formula driven cell
是否可以将一个单元格设为公式驱动的单元格并使其自动更新?类似于 Excel.
例如,我希望用户填写两个单元格,然后当用户填写两个单元格时,第三个单元格将自动划分。我希望它不连接到按钮。
QTable 截图
TableWidget 代码:
self.tableWidget = {}
for i in range(int(self.numberLine.text())):
self.tableWidget[i] = QTableWidget()
self.tableWidget[i].setRowCount(5)
self.tableWidget[i].setColumnCount(3)
self.tableWidget[i].setHorizontalHeaderLabels(['OEM (Case {})'.format(i+1), 'ZVI (Case {})'.format (i+1), 'Improvement % '])
self.tableWidget[i].setVerticalHeaderLabels(['Flow (MMSCFD)', 'HP', 'Specific Power (HP/MMSCFD)', 'Discharge Temp (F)', ''])
self.tableWidget[i].setFixedSize(QtCore.QSize(480, 180))
self.gridLayout_14.addWidget(self.tableWidget[i])
将单元格连接到其他单元格 EditingFinished 信号
一个优雅的解决方案是创建一个继承自 QTableWidget
的自定义 class,在其中连接 itemChanged
信号,每次单元格更改值时都会发出此信号(此 returns 已更改的项目,但将仅使用它来验证默认列是否已更改)。
除了没有用户将不同的值放置到浮动的问题之外,我们将使用 QDoubleValidator,为此我们创建了一个自定义 QItemDelegate。
class FloatDelegate(QItemDelegate):
def __init__(self, _from, _to, _n_decimals, parent=None):
QItemDelegate.__init__(self, parent=parent)
self._from = _from
self._to = _to
self._n_decimals = _n_decimals
def createEditor(self, parent, option, index):
lineEdit = QLineEdit(parent)
_n_decimals = 2
validator = QDoubleValidator(self._from, self._to, self._n_decimals, lineEdit)
lineEdit.setValidator(validator)
return lineEdit
class CustomTableWidget(QTableWidget):
_from = 0
_to = 10**5
_n_decimals = 2
def __init__(self, i, parent=None):
QTableWidget.__init__(self, 5, 3, parent=parent)
self.setItemDelegate(FloatDelegate(self._from, self._to, self._n_decimals, self))
self.setHorizontalHeaderLabels(['OEM (Case {})'.format(i+1), 'ZVI (Case {})'.format (i+1), 'Improvement % '])
self.setVerticalHeaderLabels(['Flow (MMSCFD)', 'HP', 'Specific Power (HP/MMSCFD)', 'Discharge Temp (F)', ''])
self.setFixedSize(QSize(480, 180))
self.itemChanged.connect(self.onItemChanged)
def onItemChanged(self, item):
# items (2, 0) = (1, 0) / (0, 0)
if item.column() == 0 and (item.row() == 0 or item.row()==1):
num = self.item(1, 0)
den = self.item(0, 0)
if num and den:
resp = float(num.data(Qt.DisplayRole))/float(den.data(Qt.DisplayRole))
rest_string = str(round(resp, self._n_decimals))
it = QTableWidgetItem(rest_string, QTableWidgetItem.Type)
self.setItem(2, 0, it)
示例:
class Widget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
self.setLayout(QGridLayout())
for i in range(2):
self.layout().addWidget(CustomTableWidget(i))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Widget()
window.show()
sys.exit(app.exec_())
你的情况:
self.tableWidget = {}
for i in range(int(self.numberLine.text())):
self.tableWidget[i] = CustomTableWidget(i)
self.gridLayout_14.addWidget(self.tableWidget[i])
另一个不使用验证器的选项,我们可以将 QLineEdit 更改为 QDoubleSpinBox。
def createEditor(self, parent, option, index):
w = QDoubleSpinBox(parent)
_n_decimals = 2
w.setMinimum(self._from)
w.setMaximum(self._to)
w.setDecimals(self._n_decimals)
return w
是否可以将一个单元格设为公式驱动的单元格并使其自动更新?类似于 Excel.
例如,我希望用户填写两个单元格,然后当用户填写两个单元格时,第三个单元格将自动划分。我希望它不连接到按钮。
QTable 截图
TableWidget 代码:
self.tableWidget = {}
for i in range(int(self.numberLine.text())):
self.tableWidget[i] = QTableWidget()
self.tableWidget[i].setRowCount(5)
self.tableWidget[i].setColumnCount(3)
self.tableWidget[i].setHorizontalHeaderLabels(['OEM (Case {})'.format(i+1), 'ZVI (Case {})'.format (i+1), 'Improvement % '])
self.tableWidget[i].setVerticalHeaderLabels(['Flow (MMSCFD)', 'HP', 'Specific Power (HP/MMSCFD)', 'Discharge Temp (F)', ''])
self.tableWidget[i].setFixedSize(QtCore.QSize(480, 180))
self.gridLayout_14.addWidget(self.tableWidget[i])
将单元格连接到其他单元格 EditingFinished 信号
一个优雅的解决方案是创建一个继承自 QTableWidget
的自定义 class,在其中连接 itemChanged
信号,每次单元格更改值时都会发出此信号(此 returns 已更改的项目,但将仅使用它来验证默认列是否已更改)。
除了没有用户将不同的值放置到浮动的问题之外,我们将使用 QDoubleValidator,为此我们创建了一个自定义 QItemDelegate。
class FloatDelegate(QItemDelegate):
def __init__(self, _from, _to, _n_decimals, parent=None):
QItemDelegate.__init__(self, parent=parent)
self._from = _from
self._to = _to
self._n_decimals = _n_decimals
def createEditor(self, parent, option, index):
lineEdit = QLineEdit(parent)
_n_decimals = 2
validator = QDoubleValidator(self._from, self._to, self._n_decimals, lineEdit)
lineEdit.setValidator(validator)
return lineEdit
class CustomTableWidget(QTableWidget):
_from = 0
_to = 10**5
_n_decimals = 2
def __init__(self, i, parent=None):
QTableWidget.__init__(self, 5, 3, parent=parent)
self.setItemDelegate(FloatDelegate(self._from, self._to, self._n_decimals, self))
self.setHorizontalHeaderLabels(['OEM (Case {})'.format(i+1), 'ZVI (Case {})'.format (i+1), 'Improvement % '])
self.setVerticalHeaderLabels(['Flow (MMSCFD)', 'HP', 'Specific Power (HP/MMSCFD)', 'Discharge Temp (F)', ''])
self.setFixedSize(QSize(480, 180))
self.itemChanged.connect(self.onItemChanged)
def onItemChanged(self, item):
# items (2, 0) = (1, 0) / (0, 0)
if item.column() == 0 and (item.row() == 0 or item.row()==1):
num = self.item(1, 0)
den = self.item(0, 0)
if num and den:
resp = float(num.data(Qt.DisplayRole))/float(den.data(Qt.DisplayRole))
rest_string = str(round(resp, self._n_decimals))
it = QTableWidgetItem(rest_string, QTableWidgetItem.Type)
self.setItem(2, 0, it)
示例:
class Widget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
self.setLayout(QGridLayout())
for i in range(2):
self.layout().addWidget(CustomTableWidget(i))
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Widget()
window.show()
sys.exit(app.exec_())
你的情况:
self.tableWidget = {}
for i in range(int(self.numberLine.text())):
self.tableWidget[i] = CustomTableWidget(i)
self.gridLayout_14.addWidget(self.tableWidget[i])
另一个不使用验证器的选项,我们可以将 QLineEdit 更改为 QDoubleSpinBox。
def createEditor(self, parent, option, index):
w = QDoubleSpinBox(parent)
_n_decimals = 2
w.setMinimum(self._from)
w.setMaximum(self._to)
w.setDecimals(self._n_decimals)
return w