QStyledItemDelegate 绘画刷新问题
QStyledItemDelegate paint refresh issues
我目前正在尝试围绕模型视图方法编写缩略图查看器应用程序。
在这个例子中,我只是尝试绘制 20 个方框,但我得到的似乎是一个随鼠标移动而更新的随机选择。滚动让事情变得更糟,有时只绘制框等。而且文本似乎根本没有呈现。
对我来说,这看起来像是 refresh/update 绘画方法的问题。
我在这里遗漏了什么吗?
最终我需要展示很多项目。所有都包含一些标签和一个需要在运行时更新的像素图。所以我认为给它们上色是最快的解决办法。或者我尝试在 paint 方法中渲染我的小部件:
customWidget.render(painter, QtCore.QPoint(0,0), renderFlags=QtGui.QWidget.DrawChildren)
这似乎更慢,但至少可以工作。
这里有一个最小的工作示例来说明我的问题:
import sys
from PySide import QtCore
from PySide import QtGui
elements = range(20)
class ElementListModel(QtCore.QAbstractListModel):
def __init__(self, elements = [], parent = None):
super(ElementListModel, self).__init__()
self.__elements = elements
def rowCount(self, parent):
return len(self.__elements)
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return str(self.__elements[index.row()])
class ElementThumbDelegate(QtGui.QStyledItemDelegate):
def __init__(self, view, parent=None):
super(ElementThumbDelegate, self).__init__(parent)
def paint(self, painter, options, index):
width = options.rect.width()
height = options.rect.height()
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtGui.QColor(255, 255, 255))
painter.setBrush(QtGui.QColor(10, 10, 10))
painter.drawRect(0, 0, width, height)
painter.drawText(options.rect, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter, str(index.data()))
painter.translate(options.rect.topLeft())
def sizeHint(self, options, index):
return QtCore.QSize(50, 50)
def main():
app = QtGui.QApplication(sys.argv)
viewer = QtGui.QListView()
viewModel = ElementListModel(elements)
viewer.setModel(viewModel)
viewer.setViewMode(QtGui.QListView.IconMode)
viewer.setItemDelegate(ElementThumbDelegate(viewer))
viewer.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
提前致谢。非常感谢您提供任何帮助或指示下一步该去哪里!
事实证明,painter.translate()
与在查看器原点 (0,0) 处绘制框相结合会影响自动定位并导致问题。
委托到适当位置的转换由视图本身处理 - 无需手动执行。
工作代码:
import sys
from PySide import QtCore
from PySide import QtGui
elements = range(20)
class ElementListModel(QtCore.QAbstractListModel):
def __init__(self, elements = [], parent = None):
super(ElementListModel, self).__init__()
self.__elements = elements
def rowCount(self, parent):
return len(self.__elements)
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return str(self.__elements[index.row()])
class ElementThumbDelegate(QtGui.QStyledItemDelegate):
def __init__(self, view, parent=None):
super(ElementThumbDelegate, self).__init__(parent)
def paint(self, painter, options, index):
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtGui.QColor(255, 255, 255))
painter.setBrush(QtGui.QColor(10, 10, 10))
painter.drawRect(options.rect)
painter.drawText(options.rect, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter, str(index.data()))
def sizeHint(self, options, index):
return QtCore.QSize(50, 50)
def main():
app = QtGui.QApplication(sys.argv)
viewer = QtGui.QListView()
viewModel = ElementListModel(elements)
viewer.setModel(viewModel)
viewer.setViewMode(QtGui.QListView.IconMode)
viewer.setItemDelegate(ElementThumbDelegate(viewer))
viewer.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我目前正在尝试围绕模型视图方法编写缩略图查看器应用程序。
在这个例子中,我只是尝试绘制 20 个方框,但我得到的似乎是一个随鼠标移动而更新的随机选择。滚动让事情变得更糟,有时只绘制框等。而且文本似乎根本没有呈现。
对我来说,这看起来像是 refresh/update 绘画方法的问题。 我在这里遗漏了什么吗?
最终我需要展示很多项目。所有都包含一些标签和一个需要在运行时更新的像素图。所以我认为给它们上色是最快的解决办法。或者我尝试在 paint 方法中渲染我的小部件:
customWidget.render(painter, QtCore.QPoint(0,0), renderFlags=QtGui.QWidget.DrawChildren)
这似乎更慢,但至少可以工作。
这里有一个最小的工作示例来说明我的问题:
import sys
from PySide import QtCore
from PySide import QtGui
elements = range(20)
class ElementListModel(QtCore.QAbstractListModel):
def __init__(self, elements = [], parent = None):
super(ElementListModel, self).__init__()
self.__elements = elements
def rowCount(self, parent):
return len(self.__elements)
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return str(self.__elements[index.row()])
class ElementThumbDelegate(QtGui.QStyledItemDelegate):
def __init__(self, view, parent=None):
super(ElementThumbDelegate, self).__init__(parent)
def paint(self, painter, options, index):
width = options.rect.width()
height = options.rect.height()
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtGui.QColor(255, 255, 255))
painter.setBrush(QtGui.QColor(10, 10, 10))
painter.drawRect(0, 0, width, height)
painter.drawText(options.rect, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter, str(index.data()))
painter.translate(options.rect.topLeft())
def sizeHint(self, options, index):
return QtCore.QSize(50, 50)
def main():
app = QtGui.QApplication(sys.argv)
viewer = QtGui.QListView()
viewModel = ElementListModel(elements)
viewer.setModel(viewModel)
viewer.setViewMode(QtGui.QListView.IconMode)
viewer.setItemDelegate(ElementThumbDelegate(viewer))
viewer.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
提前致谢。非常感谢您提供任何帮助或指示下一步该去哪里!
事实证明,painter.translate()
与在查看器原点 (0,0) 处绘制框相结合会影响自动定位并导致问题。
委托到适当位置的转换由视图本身处理 - 无需手动执行。
工作代码:
import sys
from PySide import QtCore
from PySide import QtGui
elements = range(20)
class ElementListModel(QtCore.QAbstractListModel):
def __init__(self, elements = [], parent = None):
super(ElementListModel, self).__init__()
self.__elements = elements
def rowCount(self, parent):
return len(self.__elements)
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
return str(self.__elements[index.row()])
class ElementThumbDelegate(QtGui.QStyledItemDelegate):
def __init__(self, view, parent=None):
super(ElementThumbDelegate, self).__init__(parent)
def paint(self, painter, options, index):
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtGui.QColor(255, 255, 255))
painter.setBrush(QtGui.QColor(10, 10, 10))
painter.drawRect(options.rect)
painter.drawText(options.rect, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter, str(index.data()))
def sizeHint(self, options, index):
return QtCore.QSize(50, 50)
def main():
app = QtGui.QApplication(sys.argv)
viewer = QtGui.QListView()
viewModel = ElementListModel(elements)
viewer.setModel(viewModel)
viewer.setViewMode(QtGui.QListView.IconMode)
viewer.setItemDelegate(ElementThumbDelegate(viewer))
viewer.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()