动态控制 QItemDelegate 的大小
controlling size of QItemDelegate dynamically
我有几个关于 QItemDelegates in a QListView 尺寸的问题:
我有一个像这样的 QListView using a QItemDelegate which renders a widget in the delegate's custom paint() 方法:
self.thumbnail = MyCustomWidget()
self.thumbnail.render(painter, QtCore.QPoint(option.rect.x(), option.rect.y()))
但是,这显示 QListView, even though the MyCustomWidget().sizeHint() 中带有 250x260 图像的项目是 250x250,它的 maximumSize() returns 也是 250x250。
我发现罪魁祸首是 QListView's spacing, which I had set to 10. If I set the spacing to 100, I still get the QItemDelegates size of 250x260, but if I just don't use setSpacing() 它以 250x250 的分辨率按预期呈现。
传入 paint 方法的 spacing seems to alter the option.rect,导致大小不正确。
我确实需要 spacing, so I'm a bit confused why the QListView's spacing alters the QItemDelegates 的尺码?这是一个错误吗?
我可以通过直接渲染 QPixmap first, then have the painter draw the QPixmap instead of rendering to the painter 来解决这个问题:
self.thumbnail = MyCustomWidget()
pixmap = QtGui.QPixmap(self.thumbnail.size())
self.thumbnail.render(pixmap)
painter.drawPixmap(option.rect.topLeft(), pixmap)
这会生成我需要的 250x250 图像,但我不明白为什么当我使用 setSpacing 时第一种方法无法呈现正确的尺寸?!
现在,更大的挑战是如何动态缩放 QItemDelegate's via a QSlider 的大小:
我有一个 QSlider in the QListView 应该缩放项目,以便用户可以选择在当前视图中查看更小但更多的项目。我测试了 MyCustomWidget() 的独立实例的大小调整,它工作得很好。
但是,委托不会按预期缩放。这是我的委托代码:
class代表(QtGui.QItemDelegate):
def __init__(self, parent = None):
super(Delegate, self).__init__(parent)
self.scaleValue = 100 # size in percent (as returned by QSlider)
def paint(self, painter, option, index):
proxyModel = index.model()
item = proxyModel.sourceModel().itemFromIndex(proxyModel.mapToSource(index))
self.thumbnail = ElementThumbnail(item)
self.thumbnail.scale(self.scaleValue)
pixmap = QtGui.QPixmap(self.thumbnail.size())
self.thumbnail.render(pixmap)
painter.drawPixmap(option.rect.topLeft() * self.scaleValue / 100.0, pixmap)
super(Delegate, self).paint(painter, option, index)
def setScaleValue(self, value):
self.scaleValue = value
def sizeHint(self, option, index):
return ElementThumbnail.thumbSize * self.scaleValue / 100.0
并且在 QListView 中,我正在使用连接到滑块的 valueChanges 信号的插槽:
def scaleThumbnails(self, value):
self.itemDelegate().setScaleValue(value)
self.update()
结果是 QSlider 将裁剪 QItemDelegate 但不会缩放它们,因为 QItemDelegate 的 sizeHint() 仅在首次显示 QListView 时调用。
此外,我需要确保当小部件(最终)缩小时,重新计算 QListView 的布局并且更多项目适合可见区域。
简而言之,我的问题是:
- 如何在 QListView 中动态缩放 QItemDelegate?
- 如何强制 QListView 在代理大小更改后重新计算其布局?
编辑:至于问题 2:QAbstractItemView.doItemsLayout 似乎可以解决问题。虽然仍然想知道问题 1
谢谢,
坦率
原来问题出在我的代码的上下文上,而不是委托。
在将小部件呈现为像素图之前,我正在缩放小部件,这当然使编辑器可以正确缩放,但不是在项目不处于编辑状态时。
所以解决方案是在从小部件渲染后简单地缩放像素图,例如:
scaledPixmap = pixmap.scaled(pixmap.size() * self.scaleValue / 100.0)
painter.drawPixmap(option.rect.topLeft(), scaledPixmap)
我有几个关于 QItemDelegates in a QListView 尺寸的问题:
我有一个像这样的 QListView using a QItemDelegate which renders a widget in the delegate's custom paint() 方法:
self.thumbnail = MyCustomWidget()
self.thumbnail.render(painter, QtCore.QPoint(option.rect.x(), option.rect.y()))
但是,这显示 QListView, even though the MyCustomWidget().sizeHint() 中带有 250x260 图像的项目是 250x250,它的 maximumSize() returns 也是 250x250。
我发现罪魁祸首是 QListView's spacing, which I had set to 10. If I set the spacing to 100, I still get the QItemDelegates size of 250x260, but if I just don't use setSpacing() 它以 250x250 的分辨率按预期呈现。 传入 paint 方法的 spacing seems to alter the option.rect,导致大小不正确。 我确实需要 spacing, so I'm a bit confused why the QListView's spacing alters the QItemDelegates 的尺码?这是一个错误吗?
我可以通过直接渲染 QPixmap first, then have the painter draw the QPixmap instead of rendering to the painter 来解决这个问题:
self.thumbnail = MyCustomWidget()
pixmap = QtGui.QPixmap(self.thumbnail.size())
self.thumbnail.render(pixmap)
painter.drawPixmap(option.rect.topLeft(), pixmap)
这会生成我需要的 250x250 图像,但我不明白为什么当我使用 setSpacing 时第一种方法无法呈现正确的尺寸?!
现在,更大的挑战是如何动态缩放 QItemDelegate's via a QSlider 的大小: 我有一个 QSlider in the QListView 应该缩放项目,以便用户可以选择在当前视图中查看更小但更多的项目。我测试了 MyCustomWidget() 的独立实例的大小调整,它工作得很好。
但是,委托不会按预期缩放。这是我的委托代码: class代表(QtGui.QItemDelegate):
def __init__(self, parent = None):
super(Delegate, self).__init__(parent)
self.scaleValue = 100 # size in percent (as returned by QSlider)
def paint(self, painter, option, index):
proxyModel = index.model()
item = proxyModel.sourceModel().itemFromIndex(proxyModel.mapToSource(index))
self.thumbnail = ElementThumbnail(item)
self.thumbnail.scale(self.scaleValue)
pixmap = QtGui.QPixmap(self.thumbnail.size())
self.thumbnail.render(pixmap)
painter.drawPixmap(option.rect.topLeft() * self.scaleValue / 100.0, pixmap)
super(Delegate, self).paint(painter, option, index)
def setScaleValue(self, value):
self.scaleValue = value
def sizeHint(self, option, index):
return ElementThumbnail.thumbSize * self.scaleValue / 100.0
并且在 QListView 中,我正在使用连接到滑块的 valueChanges 信号的插槽:
def scaleThumbnails(self, value):
self.itemDelegate().setScaleValue(value)
self.update()
结果是 QSlider 将裁剪 QItemDelegate 但不会缩放它们,因为 QItemDelegate 的 sizeHint() 仅在首次显示 QListView 时调用。 此外,我需要确保当小部件(最终)缩小时,重新计算 QListView 的布局并且更多项目适合可见区域。
简而言之,我的问题是:
- 如何在 QListView 中动态缩放 QItemDelegate?
- 如何强制 QListView 在代理大小更改后重新计算其布局?
编辑:至于问题 2:QAbstractItemView.doItemsLayout 似乎可以解决问题。虽然仍然想知道问题 1
谢谢, 坦率
原来问题出在我的代码的上下文上,而不是委托。 在将小部件呈现为像素图之前,我正在缩放小部件,这当然使编辑器可以正确缩放,但不是在项目不处于编辑状态时。 所以解决方案是在从小部件渲染后简单地缩放像素图,例如:
scaledPixmap = pixmap.scaled(pixmap.size() * self.scaleValue / 100.0)
painter.drawPixmap(option.rect.topLeft(), scaledPixmap)