в моем приложении я хочу создать лист как Excel, мы вводим формулу и параметры, и у нас есть результаты;Я видел метод SpreadSheet (QTableWidget)
таблица отображается, но при первом щелчке в ячейке программа возвращает ошибку
SpreadSheet (QTableWidgetItem)
SpreadSheetDelegate (QitemDelegate (QitemDelegate))
from PyQt5 import QtCore, QtGui,QtWidgets,QtPrintSupport
from PyQt5.QtWidgets import QMainWindow,QApplication,QTableWidget,QTableWidgetItem,QInputDialog,QHBoxLayout,QItemDelegate,QLineEdit
from PyQt5.QtCore import QDir,Qt,QPointF,pyqtProperty, pyqtSignal, pyqtSlot,QDateTime#3 dernier test
from PyQt5.QtGui import QIcon,QTextDocument,QTextCursor,QPainter,QFont,QPalette,QColor,QPen,QBrush,QPixmap
import string,re
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
self.verticalLayout.addLayout(self.horizontalLayout)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "FX"))
class fusionassurf(QMainWindow):
def __init__(self):
super(fusionassurf,self).__init__()
self.ui=Ui_MainWindow()
self.ui.setupUi(self)
self.ui.tableWidget=Spreadsheet(self)
self.ui.verticalLayout.addWidget(self.ui.tableWidget)
self.ui.tableWidget.cellClicked.connect(self.onClickItem)
self.ui.tableWidget.cellActivated.connect(self.onClickItem)
def onClickItem(self):
# return value of formule in QLineEdit
pass
class Spreadsheet(QTableWidget):
def __init__(self, parent=None):
super().__init__(parent)
_translate = QtCore.QCoreApplication.translate
self.setRowCount(20)
self.setColumnCount(26)
self.cells = {}
self.setObjectName("tableWidget")
header=[x for x in string.ascii_uppercase]
self.setHorizontalHeaderLabels(header)
self.setItemDelegate(SpreadSheetDelegate(self))
self.setSelectionMode(self.ContiguousSelection)
# test
self.autocalcul=True
#self.setItemPrototype(SpreadSheetItem('', self))
for i in range(0, self.rowCount()):
for j in range(0, self.columnCount()):
cell = SpreadSheetItem("")
self.setItem(i, j, cell)
class SpreadSheetDelegate(QItemDelegate):
def __init__(self, parent=None):
super(SpreadSheetDelegate, self).__init__(parent)
def createEditor(self, parent, styleOption, index):
editor = QLineEdit(parent)
editor.editingFinished.connect(self.commitAndCloseEditor)
return editor
def commitAndCloseEditor(self):
editor = self.sender()
self.commitData.emit(editor)
self.closeEditor.emit(editor, QItemDelegate.NoHint)
def setEditorData(self, editor, index):
editor.setText(index.model().data(index, Qt.EditRole))
def setModelData(self, editor, model, index):
model.setData(index, editor.text())
#ENCODAGE ET DECODAGE DES CELLULES REFERENCEES
cellre = re.compile(r'\b[A-Z][0-9]\b')
def cellname(i, j):
return f'{chr(ord("A")+j)}{i+1}'
def decode_pos(pos):
try:
row = int(pos[1:]) - 1
col = ord(pos[0]) - ord('A')
except ValueError:
row = -1
col = -1
return row, col
def encode_pos(row, col):
return chr(col + ord('A')) + str(row + 1)
class SpreadSheetItem(QTableWidgetItem):
def __init__(self, text=None):
if text is not None:
super(SpreadSheetItem, self).__init__(text)
else:
super(SpreadSheetItem, self).__init__()
self.isResolving = False
def clone(self):
item = super(SpreadSheetItem, self).clone()
item.isResolving = self.isResolving
return item
def formula(self):
return super(SpreadSheetItem, self).data(Qt.DisplayRole)
def data(self, role):
if role in (Qt.EditRole, Qt.StatusTipRole):
return self.formula()
if role == Qt.DisplayRole:
return self.display()
t = str(self.display())
try:
number = int(t)
except ValueError:
number = None
if role == Qt.TextColorRole:
if number is None:
return QColor(Qt.black)
elif number < 0:
return QColor(Qt.red)
return QColor(Qt.blue)
if role == Qt.TextAlignmentRole:
if t and (t[0].isdigit() or t[0] == '-'):
return Qt.AlignRight | Qt.AlignVCenter
return super(SpreadSheetItem, self).data(role)
def setData(self, role, value):
super(SpreadSheetItem, self).setData(role, value)
if self.tableWidget():
self.tableWidget().viewport().update()
def display(self):
# avoid circular dependencies
if self.isResolving:
return None
self.isResolving = True
result = self.computeFormula(self.formula(), self.tableWidget())
self.isResolving = False
return result
def computeFormula(self, formula, widget):
formula=formula.strip().replace(' ', '')
if formula =="" or formula is None:
return ""
elif formula[0]=='=':
self.formula=formula.upper()
else:
return formula
# check if the string is actually a formula or not
slist = formula.split(' ')
if not slist or not widget:
# it is a normal string
return formula
op = slist[0].lower()
firstRow = -1
firstCol = -1
secondRow = -1
secondCol = -1
if len(slist) > 1:
firstRow, firstCol = decode_pos(slist[1])
if len(slist) > 2:
secondRow, secondCol = decode_pos(slist[2])
start = widget.item(firstRow, firstCol)
end = widget.item(secondRow, secondCol)
firstVal = 0
try:
firstVal = start and int(start.text()) or 0
except ValueError:
pass
secondVal = 0
try:
secondVal = end and int(end.text()) or 0
except ValueError:
pass
result = None
if op == "sum":
sum_ = 0
for r in range(firstRow, secondRow + 1):
for c in range(firstCol, secondCol + 1):
tableItem = widget.item(r, c)
if tableItem and tableItem != self:
try:
sum_ += int(tableItem.text())
except ValueError:
pass
result = sum_
elif op == "+":
result = (firstVal + secondVal)
elif op == "-":
result = (firstVal - secondVal)
elif op == "*":
result = (firstVal * secondVal)
elif op == "/":
if secondVal == 0:
result = "nan"
else:
result = (firstVal / secondVal)
elif op == "=":
if start:
result = start.text()
else:
result = formula
return result
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
locale=QtCore.QLocale.system().name()
window =fusionassurf()
window.show()
sys.exit(app.exec_())
Я ожидаю результат значения формулы в ячейке