gpt4 book ai didi

python - 将 QCheckBox 定位在 QListView 项目的左上角

转载 作者:行者123 更新时间:2023-12-04 15:41:01 30 4
gpt4 key购买 nike

如何将 QListView 中项目的复选框定位在左上角?我尝试使用样式表,但当我调整项目大小时,复选框不会保持其在左上角的位置。它变得隐藏。

有没有人对如何实现这一目标有任何建议?我是使用 QItemDelegate 还是 QStyledItemDelegate 来解决我的问题?

我的目标是让它看起来像这样......

enter image description here

import os, sys, re
from Qt import QtWidgets, QtGui, QtCore
from PictureShop.Resources import StyleUtils


################################################################################
# Dummy Values
################################################################################
values = ['MomBod','Colonel','Tater','Tot','Ginger','Donut','Sport','LaLa','Itchy','Bruiser','Cotton','Cumulus','Toodles']


################################################################################
# Widgets
################################################################################
class ViewerWidget(QtWidgets.QWidget):

def __init__(self):
QtWidgets.QWidget.__init__(self)
self.resize(500,500)

self.uiIconSize = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.uiIconSize.setRange(32,256)
self.uiIconSize.setValue(96)
self.uiIconSize.setMinimumWidth(100)

self.viewerModel = QtGui.QStandardItemModel()
self.uiListView = QtWidgets.QListView()
self.uiListView.setSpacing(5)
self.uiListView.setMovement(QtWidgets.QListView.Static)
self.uiListView.setViewMode(QtWidgets.QListView.IconMode)
self.uiListView.setLayoutMode(QtWidgets.QListView.Batched)
self.uiListView.setBatchSize(100)
self.uiListView.setFlow(QtWidgets.QListView.LeftToRight)
self.uiListView.setWrapping(True)
self.uiListView.setResizeMode(QtWidgets.QListView.Adjust)
self.uiListView.setDragEnabled(False)
self.uiListView.setUniformItemSizes(True)
self.uiListView.setSelectionMode(QtWidgets.QListView.ExtendedSelection)
self.uiListView.setModel(self.viewerModel)

# layout
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.uiListView)
self.layout.addWidget(self.uiIconSize)
self.setLayout(self.layout)

# Signals
self.uiIconSize.valueChanged.connect(self.slotChangedIconSize)
self.uiIconSize.setValue(96)
self.uiListView.setIconSize(QtCore.QSize(96,96))

# Init
self.populateModel()
self.setStyleSheet('''
QWidget::indicator {
subcontrol-position: top center;
position: relative;
left: 30px;
top: -20px;
}

''')


# Methods
def populateModel(self):
model = self.viewerModel
model.clear()

icon = QtGui.QIcon('C:/Users/jmartini/Desktop/brokenImage.png')
for x in values:
newItem = QtGui.QStandardItem()
newItem.setCheckable(True)
newItem.setData(icon, role=QtCore.Qt.DecorationRole)
model.appendRow(newItem)


# Slots
def slotChangedIconSize(self):
size = self.uiIconSize.value()
self.uiListView.setIconSize(QtCore.QSize(size,size))


################################################################################
# Unit Testing
################################################################################
def test_ViewerWidget():
app = QtWidgets.QApplication(sys.argv)
app.setOrganizationName('mine')
app.setApplicationName('browser')
ex = ViewerWidget()
ex.show()
sys.exit(app.exec_())


if __name__ == '__main__':
pass
test_ViewerWidget()

从下面的答案中得到帮助。我在这里显示了一个错误:

enter image description here

根据以下评论得到了一个可行的解决方案:

import os, sys, re
from Qt import QtWidgets, QtGui, QtCore


################################################################################
# Dummy Values
################################################################################
values = ['MomBod','Colonel','Tater','Tot','Ginger','Donut','Sport','LaLa','Itchy','Bruiser','Cotton','Cumulus','Toodles']



class ItemDelegate(QtWidgets.QStyledItemDelegate):

def __init__(self, parent=None, *args):
QtWidgets.QStyledItemDelegate.__init__(self, parent, *args)


# overrides
def sizeHint(self, option, index):
isw, ish = option.decorationSize.toTuple()
return QtCore.QSize(isw, ish)


def getCheckboxRect(self, option):
return QtCore.QRect(4, 4, 18, 18).translated(option.rect.topLeft())


def paint(self, painter, option, index):
painter.save()

# Draw
isw, ish = option.decorationSize.toTuple()
x, y, dx, dy = option.rect.x(), option.rect.y(), option.rect.width(), option.rect.height()

# Decoration
pic = index.data(QtCore.Qt.DecorationRole)
if pic:
painter.drawPixmap(x, y, pic.pixmap(isw, ish))

# Indicate Selected
painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
if option.state & QtWidgets.QStyle.State_Selected:
painter.setBrush(QtGui.QBrush(QtGui.QColor(0,70,240,128)))
else:
painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
painter.drawRect(QtCore.QRect(x, y, dx, dy))

# Checkstate
value = index.data(QtCore.Qt.CheckStateRole)
if value is not None:
opt = QtWidgets.QStyleOptionViewItem()
opt.rect = self.getCheckboxRect(option)
opt.state = opt.state & ~QtWidgets.QStyle.State_HasFocus
if value == QtCore.Qt.Unchecked:
opt.state |= QtWidgets.QStyle.State_Off
elif value == QtCore.Qt.PartiallyChecked:
opt.state |= QtWidgets.QStyle.State_NoChange
elif value == QtCore.Qt.Checked:
opt.state = QtWidgets.QStyle.State_On
style = QtWidgets.QApplication.style()
style.drawPrimitive(
QtWidgets.QStyle.PE_IndicatorViewItemCheck, opt, painter, None
)

painter.restore()


def editorEvent(self, event, model, option, index):
flags = model.flags(index)
if (
not (flags & QtCore.Qt.ItemIsUserCheckable)
or not (option.state & QtWidgets.QStyle.State_Enabled)
or not (flags & QtCore.Qt.ItemIsEnabled)
):
return False

value = index.data(QtCore.Qt.CheckStateRole)
if value is None:
return False

style = QtWidgets.QApplication.style()
if event.type() in (
QtCore.QEvent.MouseButtonRelease,
QtCore.QEvent.MouseButtonDblClick,
QtCore.QEvent.MouseButtonPress,
):
viewOpt = QtWidgets.QStyleOptionViewItem(option)
self.initStyleOption(viewOpt, index)
checkRect = self.getCheckboxRect(viewOpt)
if event.button() != QtCore.Qt.LeftButton or not checkRect.contains(
event.pos()
):
return False
if event.type() in (
QtCore.QEvent.MouseButtonPress,
QtCore.QEvent.MouseButtonDblClick,
):
return True
elif event.type() == QtCore.QEvent.KeyPress:
if event.key() not in (QtCore.Qt.Key_Space, QtCore.Qt.Key_Select):
return False
else:
return False
state = value
if flags & QtCore.Qt.ItemIsTristate:
state = QtCore.Qt.CheckState((state + 1) % 3)
else:
state = (
QtCore.Qt.Unchecked if state == QtCore.Qt.Checked else QtCore.Qt.Checked
)
return model.setData(index, state, QtCore.Qt.CheckStateRole)

################################################################################
# Widgets
################################################################################
class ViewerWidget(QtWidgets.QWidget):

def __init__(self):
QtWidgets.QWidget.__init__(self)
self.resize(500,500)

self.uiIconSize = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.uiIconSize.setRange(32,256)
self.uiIconSize.setValue(96)
self.uiIconSize.setMinimumWidth(100)

self.viewerModel = QtGui.QStandardItemModel()
self.uiListView = QtWidgets.QListView()
self.uiListView.setSpacing(5)
self.uiListView.setMovement(QtWidgets.QListView.Static)
self.uiListView.setViewMode(QtWidgets.QListView.IconMode)
self.uiListView.setLayoutMode(QtWidgets.QListView.Batched)
self.uiListView.setBatchSize(100)
self.uiListView.setFlow(QtWidgets.QListView.LeftToRight)
self.uiListView.setWrapping(True)
self.uiListView.setResizeMode(QtWidgets.QListView.Adjust)
self.uiListView.setDragEnabled(False)
self.uiListView.setUniformItemSizes(True)
self.uiListView.setSelectionMode(QtWidgets.QListView.ExtendedSelection)
self.uiListView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.uiListView.setModel(self.viewerModel)
self.uiListView.setItemDelegate(ItemDelegate())

# layout
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.uiListView)
self.layout.addWidget(self.uiIconSize)
self.setLayout(self.layout)

# Signals
self.uiIconSize.valueChanged.connect(self.slotChangedIconSize)
self.uiIconSize.setValue(96)
self.uiListView.setIconSize(QtCore.QSize(96,96))

# Init
self.populateModel()


# Methods
def populateModel(self):
model = self.viewerModel
model.clear()



icon = QtGui.QIcon("C:/Users/JokerMartini-Asus/Desktop/thumbnail_image.png")
for x in values:
newItem = QtGui.QStandardItem()
newItem.setCheckable(True)
newItem.setData(icon, role=QtCore.Qt.DecorationRole)
model.appendRow(newItem)


# Slots
def slotChangedIconSize(self):
size = self.uiIconSize.value()
self.uiListView.setIconSize(QtCore.QSize(size,size))


################################################################################
# Unit Testing
################################################################################
def test_ViewerWidget():
app = QtWidgets.QApplication(sys.argv)
app.setOrganizationName('mine')
app.setApplicationName('browser')
ex = ViewerWidget()
ex.show()
sys.exit(app.exec_())


if __name__ == '__main__':
pass
test_ViewerWidget()

最佳答案

使用委托(delegate),您可以在绘制图标后进行绘制:

class Delegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super(Delegate, self).initStyleOption(option, index)
option.features &= ~QtWidgets.QStyleOptionViewItem.HasCheckIndicator

def paint(self, painter, option, index):
super(Delegate, self).paint(painter, option, index)
value = index.data(QtCore.Qt.CheckStateRole)
if value is not None:
opt = QtWidgets.QStyleOptionViewItem()
opt.rect = self.checkRect(option)
opt.state = opt.state & ~QtWidgets.QStyle.State_HasFocus
if value == QtCore.Qt.Unchecked:
opt.state |= QtWidgets.QStyle.State_Off
elif value == QtCore.Qt.PartiallyChecked:
opt.state |= QtWidgets.QStyle.State_NoChange
elif value == QtCore.Qt.Checked:
opt.state = QtWidgets.QStyle.State_On
widget = option.widget
style = QtWidgets.QApplication.style() if widget is None else widget.style()
style.drawPrimitive(
QtWidgets.QStyle.PE_IndicatorViewItemCheck, opt, painter, widget
)

def checkRect(self, option):
height = option.rect.height()
x, y, w, h = (f * height for f in (0.15, 0.15, 0.2, 0.2))
return QtCore.QRect(x, y, w, h).translated(option.rect.topLeft())

def editorEvent(self, event, model, option, index):
# https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/itemviews/qstyleditemdelegate.cpp?h=5.13#n278
flags = model.flags(index)
if (
not (flags & QtCore.Qt.ItemIsUserCheckable)
or not (option.state & QtWidgets.QStyle.State_Enabled)
or not (flags & QtCore.Qt.ItemIsEnabled)
):
return False
value = index.data(QtCore.Qt.CheckStateRole)
if value is None:
return False
widget = option.widget
style = widget.style() if widget is not None else QtWidgets.QApplication.style()
if event.type() in (
QtCore.QEvent.MouseButtonRelease,
QtCore.QEvent.MouseButtonDblClick,
QtCore.QEvent.MouseButtonPress,
):
viewOpt = QtWidgets.QStyleOptionViewItem(option)
self.initStyleOption(viewOpt, index)
checkRect = self.checkRect(viewOpt)
if event.button() != QtCore.Qt.LeftButton or not checkRect.contains(
event.pos()
):
return False
if event.type() in (
QtCore.QEvent.MouseButtonPress,
QtCore.QEvent.MouseButtonDblClick,
):
return True
elif event.type() == QtCore.QEvent.KeyPress:
if event.key() not in (QtCore.Qt.Key_Space, QtCore.Qt.Key_Select):
return False
else:
return False
state = value
if flags & QtCore.Qt.ItemIsUserTristate:
state = QtCore.Qt.CheckState((state + 1) % 3)

else:
state = (
QtCore.Qt.Unchecked if state == QtCore.Qt.Checked else QtCore.Qt.Checked
)
return model.setData(index, state, QtCore.Qt.CheckStateRole)

关于python - 将 QCheckBox 定位在 QListView 项目的左上角,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57793643/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com