alphanumeric
alphanumeric

Reputation: 19329

How to set text to QLineEdit when it is used as QItemDelegate with QTableView

The code below creates a single QTableView. An instance of QAbstractTableModel is then created and assigned to it as its model. Lastly, the QItemDelegate is assigned to the QTableView.

The column 0 is being populated with QLineEdit. While column 1 is populated with QComboBox. But even while QLineEdit is assigned a custom text value the QLineEdit remains to be blank. It doesn't happen with QComboBox which properly gets three items: 'Somewhere', 'Over', 'The Rainbow'.

enter image description here

What should be done to pre-populate column 0 QLineEdits with the text?

from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])

class Delegate(QtGui.QItemDelegate):
    def __init__(self):
        QtGui.QItemDelegate.__init__(self)

    def createEditor(self, parent, option, index):
        if index.column()==0:
            lineedit=QtGui.QLineEdit(parent)
            lineedit.setText('Somewhere over the rainbow')
            return lineedit
        elif index.column()==1:
            combo=QtGui.QComboBox(parent)
            combo.addItems(['Somewhere','Over','The Rainbow'])
            combo.setCurrentIndex(index.row())
            return combo

class Model(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.items = [[1, 'one', None], [2, 'two', None], [3, 'three', None]]

    def rowCount(self, parent=QtCore.QModelIndex()):
        return 3 
    def columnCount(self, parent=QtCore.QModelIndex()):
        return 3

    def data(self, index, role):
        if not index.isValid(): return
        row = index.row()
        column = index.column() 
        if role == QtCore.Qt.DisplayRole:
            return self.items[row][column]

tableModel=Model()
tableView=QtGui.QTableView() 
tableView.setModel(tableModel)
tableView.setItemDelegate(Delegate())

for row in range(tableModel.rowCount()):
    for column in range(tableModel.columnCount()):
        index=tableModel.index(row, column)
        tableView.openPersistentEditor(index)

tableView.show()
app.exec_()

EDITED LATER:

Big thanks Fabio for the trick.

Working code is posted below.

Instead of handling the value assignment inside of Delegate.createEditor() method we should implement Delegate.setEditorData(editor, index) instead. Inside of setEditorData we can get both: index.column() and index.row() as well as to access self.items variable used by model using index argument value = index.model().items[row][column]

enter image description here

from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])

class Delegate(QtGui.QItemDelegate):
    def __init__(self):
        QtGui.QItemDelegate.__init__(self)

    def createEditor(self, parent, option, index):
        if index.column()==0:
            lineedit=QtGui.QLineEdit(parent)
            return lineedit

        elif index.column()==1:
            combo=QtGui.QComboBox(parent)
            return combo

    def setEditorData(self, editor, index):
        row = index.row()
        column = index.column()
        value = index.model().items[row][column]
        if isinstance(editor, QtGui.QComboBox):
            editor.addItems(['Somewhere','Over','The Rainbow'])
            editor.setCurrentIndex(index.row())
        if isinstance(editor, QtGui.QLineEdit):
            editor.setText('Somewhere over the rainbow')

class Model(QtCore.QAbstractTableModel):
    def __init__(self):
        QtCore.QAbstractTableModel.__init__(self)
        self.items = [[1, 'one', 'ONE'], [2, 'two', 'TWO'], [3, 'three', 'THREE']]

    def flags(self, index):
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
    def rowCount(self, parent=QtCore.QModelIndex()):
        return 3 
    def columnCount(self, parent=QtCore.QModelIndex()):
        return 3

    def data(self, index, role):
        if not index.isValid(): return 
        row = index.row()
        column = index.column()
        if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
            return self.items[row][column]

tableModel=Model()
tableView=QtGui.QTableView() 
tableView.setModel(tableModel)
tableView.setItemDelegate(Delegate())

for row in range(tableModel.rowCount()):
    for column in range(tableModel.columnCount()):
        index=tableModel.index(row, column)
        tableView.openPersistentEditor(index)

tableView.show()
app.exec_()

Upvotes: 2

Views: 3201

Answers (1)

Fabio
Fabio

Reputation: 2602

The item delegate set the editor data by setEditorData method, that takes the model data and set it to the editor. In this case, the item delegate takes the model data (that maybe is empty) and set it to the QLineEdit, so it set an empty string.

If you want to initialize the data in the editor, you have to reimplement setEditorData, or initialize the data in your model.

For QComboBox, the items are displayed correcly because setEditorData doesn't change the items of the combo box. In general you have to reimplement setEditorData to set the current index of the combo box depending on the model data.

I suggest to read the documentation: Model/View Programming and Delegate Classes

Upvotes: 3

Related Questions