0

Running the python program whose code is shown below I got "error zsh: segmentation fault". The program simply displays a form containing an empty QTableWidget and when the QPushButton 'pbNuovoMargine' is clicked it inserts a new row in the QTableWidget; upon the input of each item in the QTableWidget it calls a function to align the fields entered using delegates. The problem is occurring when the function for fields alignment is called: what is happening is the first value entered at position 0,0 is aligned as expected while when starting entering the second value generates the error "error zsh: segmentation fault". It seems that the 'itemChanged' signal is emitted not only when the item is changed. Any help is appreciated

import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QSize, Qt, QModelIndex
from PyQt5.QtWidgets import QApplication, QTableView,QWidget
from PyQt5.QtWidgets import  QPushButton, QItemDelegate, QStyledItemDelegate
from gestione_gross_marginUi import Ui_f_GrossMargin

class GrossMargin(QWidget, Ui_f_GrossMargin):
    def __init__(self):
        super().__init__()      
        
        self.setupUi(self)
        self.impostazione_data_mapper()
       
        self.tW_GrossMargin.itemChanged.connect(self.allinea_campi)
        self.pbNuovoMargine.clicked.connect(self.nuovo_margine)
    
    def impostazione_data_mapper(self):
        font = QtGui.QFont()
        font.setBold(True)
        self.tW_GrossMargin.setColumnCount(7)
        self.tW_GrossMargin.setRowCount(10)
        self.tW_GrossMargin.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
        
        intestazioni=[]
        intestazioni.append("Range - quantità da")
        intestazioni.append("Range - quantità a")
        intestazioni.append("Vendita - Gross margin Italia")
        intestazioni.append("Vendita - Gross margin Estero")
        intestazioni.append("Conto lavorazione - Gross margin Italia")
        intestazioni.append("Conto lavorazione - Gross margin Estero")
        intestazioni.append(" ")
        self.tW_GrossMargin.setHorizontalHeaderLabels(intestazioni)
        
        self.tW_GrossMargin.resizeColumnsToContents()
        header = self.tW_GrossMargin.horizontalHeader()
        header.setDefaultAlignment(Qt.AlignCenter|Qt.AlignVCenter)
        self.tW_GrossMargin.resizeColumnsToContents()

        for c in range(self.tW_GrossMargin.columnCount() - 1):
         h_item = self.tW_GrossMargin.horizontalHeaderItem(c)
         h_item.setFont(font)

        self.tW_GrossMargin.resizeColumnsToContents() 


    def allinea_campi(self):
      r=self.tW_GrossMargin.currentRow()
      c=self.tW_GrossMargin.currentColumn()
      if c==0 or c==1:
         self.tW_GrossMargin.setItemDelegateForColumn(c, IntDelegate(self.tW_GrossMargin))
      else:
         self.tW_GrossMargin.setItemDelegate(FloatDelegate(3, self.tW_GrossMargin))
 
    def nuovo_margine(self):  
  
      numRows = self.tW_GrossMargin.rowCount()
      self.tW_GrossMargin.insertRow(numRows)    
         
class IntDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
      super().__init__()
   
    def paint(self, painter, option, index):    
        value = index.model().data(index, Qt.EditRole) 
        print(value)
        number=str(value)    
        painter.drawText(option.rect, Qt.AlignCenter, number)
              
class FloatDelegate(QItemDelegate):
    def __init__(self, decimals, parent=None):
        QItemDelegate.__init__(self, parent=parent)
        self.nDecimals = decimals

    def paint(self, painter, option, index):
          value = index.model().data(index, Qt.EditRole)
          try:
             number = float(value)
             painter.drawText(option.rect, int(Qt.AlignCenter | Qt.AlignVCenter), "{:.{}f}".format(number, self.nDecimals))
          except :
             QItemDelegate.paint(self, painter, option, index)

app = QApplication(sys.argv)
window = GrossMargin()
window.show()
sys.exit(app.exec_())

-- .ui file --

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_f_GrossMargin(object):
    def setupUi(self, f_GrossMargin):
        f_GrossMargin.setObjectName("f_GrossMargin")
        f_GrossMargin.resize(636, 315)
        self.gridLayout = QtWidgets.QGridLayout(f_GrossMargin)
        self.gridLayout.setObjectName("gridLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.tW_GrossMargin = QtWidgets.QTableWidget(f_GrossMargin)
        self.tW_GrossMargin.setStyleSheet("background-color: rgb(255, 251, 0);\n"
"border-color: rgb(255, 38, 0);\n"
"")
        self.tW_GrossMargin.setObjectName("tW_GrossMargin")
        self.tW_GrossMargin.setColumnCount(0)
        self.tW_GrossMargin.setRowCount(0)
        
        self.verticalLayout.addWidget(self.tW_GrossMargin)
        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.pbNuovoMargine = QtWidgets.QPushButton(f_GrossMargin)
        self.pbNuovoMargine.setObjectName("pbNuovoMargine")
        self.horizontalLayout.addWidget(self.pbNuovoMargine)
        self.pushButton_2 = QtWidgets.QPushButton(f_GrossMargin)
        self.pushButton_2.setObjectName("pushButton_2")
        self.horizontalLayout.addWidget(self.pushButton_2)
        self.pushButton_3 = QtWidgets.QPushButton(f_GrossMargin)
        self.pushButton_3.setObjectName("pushButton_3")
        self.horizontalLayout.addWidget(self.pushButton_3)
        self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)

        self.retranslateUi(f_GrossMargin)
        QtCore.QMetaObject.connectSlotsByName(f_GrossMargin)

    def retranslateUi(self, f_GrossMargin):
        _translate = QtCore.QCoreApplication.translate
        f_GrossMargin.setWindowTitle(_translate("f_GrossMargin", "Impostazione Gross Margin"))
        self.pbNuovoMargine.setText(_translate("f_GrossMargin", "Nuovo margine"))
        self.pushButton_2.setText(_translate("f_GrossMargin", "PushButton"))
        self.pushButton_3.setText(_translate("f_GrossMargin", "PushButton"))
MDR
  • 39
  • 1
  • 6
  • Why, *why* are you trying to change the delegate whenever any item changes??? – musicamante Jun 17 '22 at 09:44
  • Well, I didn't want to change the delegate... my goal is to align the item value, right after it's entered in the QTableWidget cell but, most likely, I misunderstood the point. Which would be, in your view, the correct way to be implemented for getting the result ? Thanks for the support – MDR Jun 17 '22 at 13:34
  • Once a delegate is set for a column, it will be used for any cell in that column, so continuously setting the delegate is pointless, and doing it when the data is changed is also wrong. Follow the answer that uses the delegate in the duplicate post, and just set the delegate in the `__init__` for both columns. That said, I strongly suggest you to be more careful with indentation: it's completely inconsistent in your code, and that makes it much difficult to read. – musicamante Jun 17 '22 at 14:22
  • I did not find what you mentioned "Follow the answer that uses the delegate in the duplicate post" but, thanks to your explanation, I sorted the issue out. Sorry for the problem caused by the indentation, I will pay attention more carefully – MDR Jun 18 '22 at 13:09
  • Your question has been marked as duplicate of an existing one, which has three answers, one of which (not the accepted one) uses a delegate. Use that solution. – musicamante Jun 18 '22 at 13:12

0 Answers0