如何编辑列公式使其自动计算?
How to edit column formula so it can be calculated automatically?
我正在使用 python 制作一个项目,它的行为类似于 excel,例如,当我在我的单元格中输入一些数字时,它将 自动计算 在具有已定义算法的另一个单元格中。
我尝试过实施一些想法,但我卡住了。我只能做简单的计算,比如加法和乘法。当我尝试编辑代码以允许它执行任何形式的复杂计算时遇到问题。
...
def print_it(self,no):
if no.column()==2:
return
try:
add = 10
for column in range(0,2):
try:
add*=int(self.table.item(no.row(),column).text())
except:
pass
self.table.setItem(no.row(),2,QtWidgets.QTableWidgetItem(str(add)))
except Exception as E:
print(E)
当公式为 (X^2 + Y^2) 时,我可以获得 IKS 值的正确方法是什么?
这是我的 table
你必须使用 itemChanged 信号来通知你某个项目的变化,然后你必须验证它是否是你想要的列,如果是,然后进行相应的计算。
from PyQt5 import QtCore, QtGui, QtWidgets
#
class DoubleDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
editor = QtWidgets.QDoubleSpinBox(parent)
editor.setFrame(False)
editor.setMinimum(-1.7976931348623157e308)
editor.setMaximum(1.7976931348623157e308)
editor.setSizePolicy(
QtWidgets.QSizePolicy.Ignored, editor.sizePolicy().verticalPolicy()
)
return editor
class EmptyDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
return None
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tablewidget = QtWidgets.QTableWidget(4, 7)
self.tablewidget.setHorizontalHeaderLabels(
["X", "Y", "f", "A", "IKS", "PGA", "GSS"]
)
self.tablewidget.itemChanged.connect(self.on_itemChanged)
for col in (0, 1):
delegate = DoubleDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
for col in (4,):
delegate = EmptyDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
self.setCentralWidget(self.tablewidget)
@QtCore.pyqtSlot("QTableWidgetItem*")
def on_itemChanged(self, item):
if item.column() in (0, 1):
self.calculate_iks(item.row())
def calculate_iks(self, row):
self.tablewidget.blockSignals(True)
for col in (0, 1):
it = self.tablewidget.item(row, col)
if it is None:
it = QtWidgets.QTableWidgetItem("0")
self.tablewidget.setItem(row, col, it)
self.tablewidget.blockSignals(False)
it_x = self.tablewidget.item(row, 0)
it_y = self.tablewidget.item(row, 1)
x = float(it_x.text())
y = float(it_y.text())
iks = x ** 2 + y ** 2
it_iks = self.tablewidget.item(row, 4)
if it_iks is None:
it_iks = QtWidgets.QTableWidgetItem()
self.tablewidget.setItem(row, 4, it_iks)
it_iks.setText(str(iks))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
如果你想计算 gss = iks * pga
那么你应该执行以下操作:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tablewidget = QtWidgets.QTableWidget(4, 7)
self.tablewidget.setHorizontalHeaderLabels(
["X", "Y", "f", "A", "IKS", "PGA", "GSS"]
)
self.tablewidget.itemChanged.connect(self.on_itemChanged)
for col in (0, 1, 5):
delegate = DoubleDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
for col in (4, 6,):
delegate = EmptyDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
self.setCentralWidget(self.tablewidget)
@QtCore.pyqtSlot("QTableWidgetItem*")
def on_itemChanged(self, item):
if item.column() in (0, 1):
self.calculate_iks(item.row())
elif item.column() in (4, 5):
self.calculate_gss(item.row())
# ...
def calculate_gss(self, row):
self.tablewidget.blockSignals(True)
for col in (4, 5, 6):
it = self.tablewidget.item(row, col)
if it is None:
it = QtWidgets.QTableWidgetItem("0")
self.tablewidget.setItem(row, col, it)
self.tablewidget.blockSignals(False)
it_iks = self.tablewidget.item(row, 4)
it_pga = self.tablewidget.item(row, 5)
iks = float(it_iks.text())
pga = float(it_pga.text())
gss = iks*pga
it_gss = self.tablewidget.item(row, 6)
it_gss.setText(str(gss))
我建议分析解决方案,而不仅仅是应用,因为那是SO的思想,如果在计算iks和gss的情况下进行,你会发现有很多相似之处,这样你就可以重构代码以简单的方式进行其他计算。
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tablewidget = QtWidgets.QTableWidget(4, 7)
self.tablewidget.setHorizontalHeaderLabels(
["X", "Y", "f", "A", "IKS", "PGA", "GSS"]
)
self.tablewidget.itemChanged.connect(self.on_itemChanged)
for col in (0, 1, 5):
delegate = DoubleDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
for col in (4, 6):
delegate = EmptyDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
self.setCentralWidget(self.tablewidget)
self.calculates = [
{
"inputs": (0, 1), # X, Y
"output": 4, # IKS
"function": lambda X, Y: X ** 2 + Y ** 2,
},
{
"inputs": (4, 5), # IKS, PGA
"output": 6, # GSS
"function": lambda IKS, PGA: IKS * PGA,
},
]
@QtCore.pyqtSlot("QTableWidgetItem*")
def on_itemChanged(self, item):
for c in self.calculates:
inputs = c["inputs"]
output = c["output"]
function = c["function"]
if item.column() in inputs:
self.calculate(item.row(), inputs, output, function)
def calculate(self, row, inputs, output, function):
self.tablewidget.blockSignals(True)
for col in (*inputs, output):
it = self.tablewidget.item(row, col)
if it is None:
it = QtWidgets.QTableWidgetItem("0")
self.tablewidget.setItem(row, col, it)
self.tablewidget.blockSignals(False)
values = [float(self.tablewidget.item(row, i).text()) for i in inputs]
result = function(*values)
it_out = self.tablewidget.item(row, output)
it_out.setText(str(result))
我正在使用 python 制作一个项目,它的行为类似于 excel,例如,当我在我的单元格中输入一些数字时,它将 自动计算 在具有已定义算法的另一个单元格中。
我尝试过实施一些想法,但我卡住了。我只能做简单的计算,比如加法和乘法。当我尝试编辑代码以允许它执行任何形式的复杂计算时遇到问题。
...
def print_it(self,no):
if no.column()==2:
return
try:
add = 10
for column in range(0,2):
try:
add*=int(self.table.item(no.row(),column).text())
except:
pass
self.table.setItem(no.row(),2,QtWidgets.QTableWidgetItem(str(add)))
except Exception as E:
print(E)
当公式为 (X^2 + Y^2) 时,我可以获得 IKS 值的正确方法是什么?
这是我的 table
你必须使用 itemChanged 信号来通知你某个项目的变化,然后你必须验证它是否是你想要的列,如果是,然后进行相应的计算。
from PyQt5 import QtCore, QtGui, QtWidgets
#
class DoubleDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
editor = QtWidgets.QDoubleSpinBox(parent)
editor.setFrame(False)
editor.setMinimum(-1.7976931348623157e308)
editor.setMaximum(1.7976931348623157e308)
editor.setSizePolicy(
QtWidgets.QSizePolicy.Ignored, editor.sizePolicy().verticalPolicy()
)
return editor
class EmptyDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
return None
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tablewidget = QtWidgets.QTableWidget(4, 7)
self.tablewidget.setHorizontalHeaderLabels(
["X", "Y", "f", "A", "IKS", "PGA", "GSS"]
)
self.tablewidget.itemChanged.connect(self.on_itemChanged)
for col in (0, 1):
delegate = DoubleDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
for col in (4,):
delegate = EmptyDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
self.setCentralWidget(self.tablewidget)
@QtCore.pyqtSlot("QTableWidgetItem*")
def on_itemChanged(self, item):
if item.column() in (0, 1):
self.calculate_iks(item.row())
def calculate_iks(self, row):
self.tablewidget.blockSignals(True)
for col in (0, 1):
it = self.tablewidget.item(row, col)
if it is None:
it = QtWidgets.QTableWidgetItem("0")
self.tablewidget.setItem(row, col, it)
self.tablewidget.blockSignals(False)
it_x = self.tablewidget.item(row, 0)
it_y = self.tablewidget.item(row, 1)
x = float(it_x.text())
y = float(it_y.text())
iks = x ** 2 + y ** 2
it_iks = self.tablewidget.item(row, 4)
if it_iks is None:
it_iks = QtWidgets.QTableWidgetItem()
self.tablewidget.setItem(row, 4, it_iks)
it_iks.setText(str(iks))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
如果你想计算 gss = iks * pga
那么你应该执行以下操作:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tablewidget = QtWidgets.QTableWidget(4, 7)
self.tablewidget.setHorizontalHeaderLabels(
["X", "Y", "f", "A", "IKS", "PGA", "GSS"]
)
self.tablewidget.itemChanged.connect(self.on_itemChanged)
for col in (0, 1, 5):
delegate = DoubleDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
for col in (4, 6,):
delegate = EmptyDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
self.setCentralWidget(self.tablewidget)
@QtCore.pyqtSlot("QTableWidgetItem*")
def on_itemChanged(self, item):
if item.column() in (0, 1):
self.calculate_iks(item.row())
elif item.column() in (4, 5):
self.calculate_gss(item.row())
# ...
def calculate_gss(self, row):
self.tablewidget.blockSignals(True)
for col in (4, 5, 6):
it = self.tablewidget.item(row, col)
if it is None:
it = QtWidgets.QTableWidgetItem("0")
self.tablewidget.setItem(row, col, it)
self.tablewidget.blockSignals(False)
it_iks = self.tablewidget.item(row, 4)
it_pga = self.tablewidget.item(row, 5)
iks = float(it_iks.text())
pga = float(it_pga.text())
gss = iks*pga
it_gss = self.tablewidget.item(row, 6)
it_gss.setText(str(gss))
我建议分析解决方案,而不仅仅是应用,因为那是SO的思想,如果在计算iks和gss的情况下进行,你会发现有很多相似之处,这样你就可以重构代码以简单的方式进行其他计算。
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.tablewidget = QtWidgets.QTableWidget(4, 7)
self.tablewidget.setHorizontalHeaderLabels(
["X", "Y", "f", "A", "IKS", "PGA", "GSS"]
)
self.tablewidget.itemChanged.connect(self.on_itemChanged)
for col in (0, 1, 5):
delegate = DoubleDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
for col in (4, 6):
delegate = EmptyDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(col, delegate)
self.setCentralWidget(self.tablewidget)
self.calculates = [
{
"inputs": (0, 1), # X, Y
"output": 4, # IKS
"function": lambda X, Y: X ** 2 + Y ** 2,
},
{
"inputs": (4, 5), # IKS, PGA
"output": 6, # GSS
"function": lambda IKS, PGA: IKS * PGA,
},
]
@QtCore.pyqtSlot("QTableWidgetItem*")
def on_itemChanged(self, item):
for c in self.calculates:
inputs = c["inputs"]
output = c["output"]
function = c["function"]
if item.column() in inputs:
self.calculate(item.row(), inputs, output, function)
def calculate(self, row, inputs, output, function):
self.tablewidget.blockSignals(True)
for col in (*inputs, output):
it = self.tablewidget.item(row, col)
if it is None:
it = QtWidgets.QTableWidgetItem("0")
self.tablewidget.setItem(row, col, it)
self.tablewidget.blockSignals(False)
values = [float(self.tablewidget.item(row, i).text()) for i in inputs]
result = function(*values)
it_out = self.tablewidget.item(row, output)
it_out.setText(str(result))