Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
QItemDelegate for editing questions
JonB last edited by JonB
I have written my first
QItemDelegatesubclass to allow editing of a certain kind of data in a
QTableView. My code works fine, but I'm a touch uneasy about a couple of issues. I'd appreciate any comments.
Code is Python/PyQt, but don't let that put you C++ers off reading! It's really simple and close to C++.
I need to allow user to edit dates in a column. I have already rolled my own
JDateEdit, used elsewhere in my app. Before anyone asks, can't use Qt's
QDateEditfor that as it does not allow the date to be left empty --- I asked here about that a long time ago. Not relevant to the issues anyway. Also, I looked into
QItemEditFactoryand the example using that: decided not to go down that route, it uses Qt properties and C++ macros to accomplish and those are just a pain from Python/PyQt. So I am just doing it via subclassing
QItemDelegate. With this said, onto the code:
self.tableView.setModel(self.model) self.tableView.setItemDelegateForColumn(col, JDateItemDelegate(self.tableView))
class JDateItemDelegate(QItemDelegate): # delegate to provide a JDateEdit for editing a date nicely when it's in e.g. a JTableView def __init__(self, parent=None): super().__init__(parent) def createEditor(self, parent: QWidget, option: QStyleOptionViewItem, index: QModelIndex): return JDateEdit(parent) def setEditorData(self, dateEdit: JDateEdit, index: QModelIndex): date = index.model().data(index, Qt.EditRole) dateEdit.setDate(date) def setModelData(self, dateEdit: JDateEdit, model: QAbstractItemModel, index: QModelIndex): date = dateEdit.date() model.setData(index, date)
That's it! I'd appreciate comments on:
Have I done anything wrong/missed anything?
Qt is usually very precise/consistent in the parameters etc. it uses.
modelparameter which I use for
model.setData()to store the data back. But
setEditorData()does not have a
modelparameter: I still need to fetch the data to edit from
model.data(), so I've had to get the model via
index.model()(which could equally have been done in
setModelData()). Why this inconsistency between the two methods --- am I missing something?
createEditor()is passed a
QModelIndexparameter but I don't use it, perhaps because I know I've only set my delegate on an appropriate column so I don't need to check? I don't seem to need to fetch the value to edit from the model here, as
setEditorData()will be called upon edit and that's where I will be doing it?
createEditor()is passed a
QStyleOptionViewItemparameter. I don't use it because I don't know what to do with it. Now, very specifically, while I was Googling earlier to find about all of this, I came across a post which I cannot now find. It said/warned to the effect of: "if you are creating your own editor widget, you should set Qt hard focus on your widget, as otherwise some events intended for your editor may go to the table view, or vice versa". Where I have written Qt hard focus it was actually some Qt attribute, something about "hard" & "focus", perhaps some style for a
QWidget? Can anyone figure what it was, because I cannot find the reference again for the life of me?
Many thanks for any answers.
First please derive from QStyledItemDelegate, QItemDelegate will hopefully go away with Qt6.
- setEditorData()/setModelData() - you forgot QModelIndex::data() which can be used in setEditorData() as a shortcut.
- createEdtior() - it's because you can create a different editor/widget for each index
- QStyleOptionViewItem - just take a look at the parameters - it's used for drawing the item so you can use it too if you want/need it.
The stuff with the hard focus I don't understand...
Thanks, that's perfect. I will change my derivation.
QModelIndex::data()which can be used in
setEditorData()as a shortcut.
Funny you should say that! Earlier I was musing to myself: "If
QModelIndexcontains a reference to the model, then a convenience method to access the data would be possible...". :) That's good, but doesn't to me answer why Qt passes the model explicitly to
setModelData()but not to
setEditorData(). It's as though they expect you to need it in the former but not in the latter, so I wondered if I was missing something.
I still wonder what that Qt hard focus thing I saw is about.... Does a widget have some "hard focus" property which affects how it receives events?
Maybe they mean StrongFocus?
You're a hero :)
Here we go https://doc.qt.io/qt-5/qabstractitemdelegate.html:
The returned editor widget should have
QMouseEventsreceived by the widget will propagate to the view.
What do you think of that? Do I need to take any action on the
QWidgetI am returning?
At least I did not yet had problems with the default behavior but it maybe depends on the type of the displayed widget - with QComboBoxes I don't have a problem here.
JonB last edited by JonB
OK, mine too seems to be working without my doing anything about
StrongFocusso I won't worry.
VRonin last edited by VRonin
but doesn't to me answer why Qt passes the model explicitly to setModelData() but not to setEditorData()
const QAbstractItemModel*you can read the data from the model and set it inside the editor but you can't performs actions that alter the model from it, that's why
setModelData()needs to have another, non-const, model passed as argument
Ahhhhh!!!!! Well, that makes sense. I wouldn't know that, because I'm Python/PyQt where we don't have any notion of
constand we can change whatever we like when we like, regardless! :)
Python/PyQt where we don't have any notion of const and we can change whatever we like when we like
A truly frightening thought....
@J.Hilk Everything about Python is frightening.... :)