Stefan
Stefan

Reputation: 123

QtableView crashes as soon two validators with QStyledItemDelegate are set

Based on the answer for this Question I went one step further and created two individual validators based on QStyledItemDelegate one for Integers one for Doubles.

Each one of the validators ist working perfectly if it is the only one set. As soon I try to set both validators (each in its individual column) the whole application is crashing.

import sys
from PyQt5.QtCore import QSize, Qt, pyqtSignal, QObject
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableView, QMessageBox,\
    QLineEdit, QWidget, QVBoxLayout, QDataWidgetMapper, QPushButton, QStyledItemDelegate
from PyQt5.QtGui import QIntValidator, QDoubleValidator

class ValidatedIntItemDelegate(QStyledItemDelegate):
    def __init__(self, bottom, top):
        QStyledItemDelegate.__init__(self)
        self.bottom = bottom
        self.top = top
    
    def createEditor(self, widget, option, index):
        editor = QLineEdit(widget)
        validator = QIntValidator(self.bottom, self.top)
        editor.setValidator(validator)
        return editor 

class ValidatedDoubleItemDelegate(QStyledItemDelegate):
    def __init__(self, bottom, top, decimals=0):
        QStyledItemDelegate.__init__(self)
        self.bottom = bottom
        self.top = top
        self.decimals = decimals
    
    def createEditor(self, widget, option, index):
        editor = QLineEdit(widget)
        validator =  QDoubleValidator(self.bottom, self.top, self.decimals)
        editor.setValidator(validator)
        return editor

class SqlModel(QSqlTableModel):
    def __init__(self, parent=None):
        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("chinook.sqlite")
        self.db.open()
        super().__init__()
        self.setupTable()
        self.setTable("Track")
        self.setSort(1, Qt.AscendingOrder)
        self.select()
        self.setEditStrategy(QSqlTableModel.OnFieldChange)
    
    def setupTable(self):
        query = QSqlQuery()
        query.exec("DROP TABLE if exists Track;")
        query.exec("create table if not exists Track ("
                "doda Text,"
                "One Text,"
                "Two Text,"
                "Three Text);")
        query.exec("INSERT into Track (doda) Values( '1' );")
        query.exec("INSERT into Track (doda) Values( '2' );")
        query.exec("INSERT into Track (doda) Values( '3' );")

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setMinimumSize(QSize(450, 200))
        widget = QWidget()        
        layout = QVBoxLayout()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.table = QTableView()
        layout.addWidget(self.table)
        self.model = SqlModel()
        self.table.setModel( self.model )

        intDelegate = ValidatedIntItemDelegate(1, 99)
        self.table.setItemDelegateForColumn(0, intDelegate)
#         doubleDelegate = ValidatedDoubleItemDelegate(1,99,2)
#         self.table.setItemDelegateForColumn(1, doubleDelegate)

app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

Does anybody has an idea how to get both validators working in parallel?

Upvotes: 1

Views: 276

Answers (1)

eyllanesc
eyllanesc

Reputation: 243947

It seems that the problem is caused because the view does not take ownership of the delegates and then they are removed from memory as they are local variables causing a Segmentation fault. The solution is to extend its life cycle by making the class attributes:

self.intDelegate = ValidatedIntItemDelegate(1, 99)
self.table.setItemDelegateForColumn(0, self.intDelegate)
self.doubleDelegate = ValidatedDoubleItemDelegate(1, 99, 2)
self.table.setItemDelegateForColumn(1, self.doubleDelegate)

Upvotes: 3

Related Questions