在解决我在前面的问题中提到的问题的过程中(问题1 https://stackoverflow.com/questions/33253745/how-to-most-efficiently-implement-a-pyside-qlistview-qasbtractitemview-for-an-sq, 问题2 https://stackoverflow.com/questions/33347230/how-to-subclass-qstyleditemdelegate-for-a-clickable-item-in-qlistview-using-pysi)独自一人,我成功地实现了一个自定义QStyledItemDelegate
这满足了我的要求。这里有一个最小工作示例说明当前状态:
import sys
import PySide.QtCore as core
import PySide.QtGui as gui
class DataRef(object):
def __init__(self, i):
self.i = i
def upperLabel(self):
return u'upperLabel {0}'.format(self.i)
def lowerLabel(self):
return u'lowerLabel {0}'.format(self.i)
def pixmap(self):
return gui.QPixmap(90, 90)
class MyListModel(core.QAbstractListModel):
def __init__(self, parent=None):
super(MyListModel, self).__init__(parent)
self._items = [DataRef(i) for i in range(20)]
def rowCount(self, parent=core.QModelIndex()):
return len(self._items)
def data(self, index, role=core.Qt.DisplayRole):
if not index.isValid():
return None
if role == core.Qt.DisplayRole:
return self._items[index.row()]
return
class MyListDelegate(gui.QStyledItemDelegate):
w = 300
imSize = 90
pad = 5
h = imSize + 2*pad
sepX = 10
def __init__(self, parent=None):
super(MyListDelegate, self).__init__(parent)
def paint(self, painter, option, index):
mouseOver = option.state in [73985, 73729]
if option.state & gui.QStyle.State_Selected:
painter.fillRect(option.rect, painter.brush())
pen = painter.pen()
painter.save()
x,y = (option.rect.x(), option.rect.y())
dataRef = index.data()
pixmap = dataRef.pixmap()
upperLabel = dataRef.upperLabel()
lowerLabel = dataRef.lowerLabel()
if mouseOver:
newPen = gui.QPen(core.Qt.green, 1, core.Qt.SolidLine)
painter.setPen(newPen)
else:
painter.setPen(pen)
painter.drawRect(x, y, self.w, self.h)
painter.setPen(pen)
x += self.pad
y += self.pad
painter.drawPixmap(x, y, pixmap)
font = painter.font()
textHeight = gui.QFontMetrics(font).height()
sX = self.imSize + self.sepX
sY = textHeight/2
font.setBold(True)
painter.setFont(font)
painter.drawText(x+sX, y-sY,
self.w-self.imSize-self.sepX, self.imSize,
core.Qt.AlignVCenter,
upperLabel)
font.setBold(False)
font.setItalic(True)
painter.setFont(font)
painter.drawText(x+sX, y+sY,
self.w-self.imSize-self.sepX, self.imSize,
core.Qt.AlignVCenter,
lowerLabel)
painter.restore()
def sizeHint(self, option, index):
return core.QSize(self.w, self.imSize+2*self.pad)
def editorEvent(self, event, model, option, index):
if event.type() == core.QEvent.MouseButtonRelease:
print 'Clicked on Item', index.row()
if event.type() == core.QEvent.MouseButtonDblClick:
print 'Double-Clicked on Item', index.row()
return True
if __name__ == '__main__':
app = gui.QApplication(sys.argv)
app.setStyleSheet('QListView::item:hover {background: none;}')
mw = gui.QMainWindow()
model = MyListModel()
view = gui.QListView()
view.setItemDelegate(MyListDelegate(parent=view))
view.setSpacing(5)
view.setModel(model)
mw.setCentralWidget(view)
mw.show()
sys.exit(app.exec_())
我使用了一个虚拟类DataRef
它返回委托的虚拟标签和像素图。委托只是一个矩形轮廓,左侧有一个像素图,右侧有 2 行格式化文本。 “editorEvent”使我能够检测单击和双击。
Problems
The MyListDelegate.paint()
函数接收option.state
对我来说似乎很奇怪的价值观。它们不对应于QStyle.State
我知道。所以我现在使用这个大的 int 数字,这是我通过简单打印得到的int(option.state)
。无论如何:效果不太好!框架的下边框不会改变它的颜色,有时会发生奇怪的事情。
谁能告诉我一个更好的方法来做到这一点?最佳情况是,使用 QStyle 中的颜色来更改轮廓和背景颜色,以便可以使用样式表进行自定义?
任何提示或解释都将受到高度赞赏。