'Qt - update view size on delegate sizeHint change
I have a QTreeView with a QStyledItemDelegate inside of it. When a certain action occurs to the delegate, its size is supposed to change. However I haven't figured out how to get the QTreeView's rows to resize in response to the delegate's editor size changing. I tried QTreeView.updateGeometry and QTreeView.repaint and a couple other things but it doesn't seem to work. Could someone point me in the right direction?
Here's a minimal reproduction (note: The code is hacky in a few places, it's just meant to be a demonstration of the problem, not a demonstration of good MVC).
Steps:
- Run the code below
- Press either "Add a label" button
- Note that the height of the row in the
QTreeViewdoes not change no matter how many times either button is clicked.
from PySide2 import QtCore, QtWidgets
_VALUE = 100
class _Clicker(QtWidgets.QWidget):
clicked = QtCore.Signal()
def __init__(self, parent=None):
super(_Clicker, self).__init__(parent=parent)
self.setLayout(QtWidgets.QVBoxLayout())
self._button = QtWidgets.QPushButton("Add a label")
self.layout().addWidget(self._button)
self._button.clicked.connect(self._add_label)
self._button.clicked.connect(self.clicked.emit)
def _add_label(self):
global _VALUE
_VALUE += 10
self.layout().addWidget(QtWidgets.QLabel("Add a label"))
self.updateGeometry() # Note: I didn't expect this to work but added it regardless
class _Delegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
widget = _Clicker(parent=parent)
viewer = self.parent()
widget.clicked.connect(viewer.updateGeometries) # Note: I expected this to work
return widget
def paint(self, painter, option, index):
super(_Delegate, self).paint(painter, option, index)
viewer = self.parent()
if not viewer.isPersistentEditorOpen(index):
viewer.openPersistentEditor(index)
def setEditorData(self, editor, index):
pass
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
def sizeHint(self, option, index):
hint = index.data(QtCore.Qt.SizeHintRole)
if hint:
return hint
return super(_Delegate, self).sizeHint(option, index)
class _Model(QtCore.QAbstractItemModel):
def __init__(self, parent=None):
super(_Model, self).__init__(parent=parent)
self._labels = ["foo", "bar"]
def columnCount(self, parent=QtCore.QModelIndex()):
return 1
def data(self, index, role):
if role == QtCore.Qt.SizeHintRole:
return QtCore.QSize(200, _VALUE)
if role != QtCore.Qt.DisplayRole:
return None
return self._labels[index.row()]
def index(self, row, column, parent=QtCore.QModelIndex()):
child = self._labels[row]
return self.createIndex(row, column, child)
def parent(self, index):
return QtCore.QModelIndex()
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return len(self._labels)
application = QtWidgets.QApplication([])
view = QtWidgets.QTreeView()
view.setModel(_Model())
view.setItemDelegate(_Delegate(parent=view))
view.show()
application.exec_()
How do I get a single row in a QTreeView, which has a persistent editor applied already to it, to tell Qt to resize in response to some change in the editor?
Note: One possible solution would be to close the persistent editor and re-open it to force Qt to redraw the editor widget. This would be generally very slow and not work in my specific situation. Keeping the same persistent editor is important.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
