Pyqt - 添加到 "IconMode" 中的 QTreeViewItem 时自定义小部件上丢失的选择突出显示

Pyqt - Lost selection highlighting on custom widget when adding to a QTreeViewItem in "IconMode"

我正在尝试创建一个自定义小部件列表,用户可以在其中单击它们打开 pictures/movies。我一切正常,但我丢失了通常随项目一起提供的 selection 突出显示。

我知道它不在那里,因为我使用的是自定义小部件。如何在小部件上获得 selection 高亮显示?我希望商品显示透明的蓝色层。

很好奇,当我将视图模式更改为 ListMode 时,您可以看到蓝色 selection。我已经在示例代码中注释掉了。

他是一个条纹背的例子,而且是我能得到的条纹背。切换列表视图和 select 项目以查看不同的行为。

import sys
from datetime import datetime
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui


class EntryWidget(QtWidgets.QWidget):

    def __init__(self):
        super(EntryWidget, self).__init__()
        self.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))

        # controls
        self.thumbnail = QtWidgets.QLabel()
        self.version = QtWidgets.QLabel()
        self.date = QtWidgets.QLabel()
        self.name = QtWidgets.QLabel()
        self.name.setAlignment(QtCore.Qt.AlignCenter)
        self.author = QtWidgets.QLabel()
        self.author.setAlignment(QtCore.Qt.AlignRight)
        self.dummy = QtWidgets.QLabel(" ")

        # layout
        main_layout = QtWidgets.QVBoxLayout()

        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)
        main_layout.addWidget(self.name)
        main_layout.addWidget(self.thumbnail)
        main_layout.addWidget(self.version)
        main_layout.addWidget(self.date)
        main_layout.addWidget(self.author)
        main_layout.addWidget(self.dummy)
        main_layout.addStretch()

        self.setLayout(main_layout)

    def set_size(self, w, h):
        self.thumbnail.setFixedSize(w, h)

    def set_version(self, name):
        self.version.setText(" Version:" + str(name))

    def set_date(self, name):
        date_string = " Date: {0}/{1}/{2}\n Time: {3}:{4}:{5}".format(
            str(name.day).zfill(2),
            str(name.month).zfill(2),
            name.year,
            name.hour,
            name.minute,
            name.second)
        self.date.setText(date_string)

    def set_name(self, name):
        self.name.setText(name)

    def set_author(self, name):
        self.author.setText(name + " ")

class QuickExample(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(QuickExample, self).__init__(parent)
        self.resize(500, 500)
        layout = QtWidgets.QVBoxLayout()

        media_list = QtWidgets.QListWidget(self)

        # switch the views and select an item
        media_list.setViewMode(QtWidgets.QListWidget.IconMode)
        # media_list.setViewMode(QtWidgets.QListWidget.ListMode)

        media_list.setResizeMode(QtWidgets.QListWidget.Adjust)
        media_list.setMovement(QtWidgets.QListWidget.Static)
        media_list.setSpacing(5)

        # dummy media, usually sourced from database
        media = [
            {"version": 1, "date": datetime.now(), "name": "Entry 01", "author": "Bob"},
            {"version": 2, "date": datetime.now(), "name": "Entry 02", "author": "John"}
        ]

        for i in media:
            # Create media Entry
            entry = EntryWidget()
            entry.set_version(i["version"])
            entry.set_date(i["date"])
            entry.set_size(128, 72)
            entry.set_name(i["name"])
            entry.set_author(i["author"])

            # Create QListWidgetItem
            media_item = QtWidgets.QListWidgetItem(media_list)

            # Set size hint
            media_item.setSizeHint(entry.sizeHint())

            # Add QListWidgetItem into QListWidget
            media_list.addItem(media_item)
            media_list.setItemWidget(media_item, entry)

        layout.addWidget(media_list)
        self.setLayout(layout)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    example = QuickExample()
    example.show()
    sys.exit(app.exec_())

好吧,我找到了一种适合我的 hacky 方法。我向 QListWidgetItem 添加了一些空白文本,并使字体非常大。这恢复了项目的突出显示。

media_item.setText("  ") # set the item with a  dummy string
media_item.setFont(QFont('Verdana', 180)) # make the font big so it covers the whole widget

经过一番研究,我发现使用 QListView 和 QItemDelegate 是实现此目的的方法。我找不到一个好的 example/tutorial 使用 PyQt5 所以我现在就用这个​​。

这是代码

from PyQt5.QtCore    import *
from PyQt5.QtGui     import *
from PyQt5.QtWidgets import *

from sys      import exit     as sysExit
from datetime import datetime as dtDateTime

class EntryWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.setCursor(QCursor(Qt.PointingHandCursor))
        self.setFocusPolicy(Qt.StrongFocus)  # Sets the Highlight when it has focus

      # Controls
        self.thumbnail = QLabel()
        self.version = QLabel()
        self.date = QLabel()
        self.name = QLabel()
        self.name.setAlignment(Qt.AlignCenter)
        self.author = QLabel()
        self.author.setAlignment(Qt.AlignRight)
        self.dummy = QLabel(" ")

      # Layout Container
        VBox = QVBoxLayout()
        VBox.setContentsMargins(0, 0, 0, 0)
        VBox.setSpacing(0)
        VBox.addWidget(self.name)
        VBox.addWidget(self.thumbnail)
        VBox.addWidget(self.version)
        VBox.addWidget(self.date)
        VBox.addWidget(self.author)
        VBox.addWidget(self.dummy)
        VBox.addStretch()

        self.setLayout(VBox)

    def set_size(self, w, h):
        self.thumbnail.setFixedSize(w, h)

    def set_version(self, name):
        self.version.setText(" Version:" + str(name))

    def set_date(self, name):
        date_string = " Date: {0}/{1}/{2}\n Time: {3}:{4}:{5}".format(
            str(name.day).zfill(2),
            str(name.month).zfill(2),
            name.year,
            name.hour,
            name.minute,
            name.second)
        self.date.setText(date_string)

    def set_name(self, name):
        self.name.setText(name)

    def set_author(self, name):
        self.author.setText(name + " ")

class QuickExample(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.resize(500, 500)

        media_list = QListWidget(self)

        # switch the views and select an item
        media_list.setViewMode(QListWidget.IconMode)

        media_list.setResizeMode(QListWidget.Adjust)
        media_list.setMovement(QListWidget.Static)
        media_list.setSpacing(5)

        # dummy media, usually sourced from database
        media = [
            {"version": 1, "date": dtDateTime.now(), "name": "Entry 01", "author": "Bob"},
            {"version": 2, "date": dtDateTime.now(), "name": "Entry 02", "author": "John"}
        ]

        for i in media:
            # Create media Entry
            entry = EntryWidget()
            entry.set_version(i["version"])
            entry.set_date(i["date"])
            entry.set_size(128, 72)
            entry.set_name(i["name"])
            entry.set_author(i["author"])

            # Create QListWidgetItem
            media_item = QListWidgetItem(media_list)

            ###########
            # the fix #
            ###########

            media_item.setText("  ") # set the item with a dummy string
            media_item.setFont(QFont('Verdana', 180)) # make the font big so it covers the whole widget

            # Set size hint
            media_item.setSizeHint(entry.sizeHint())

            # Add QListWidgetItem into QListWidget
            media_list.addItem(media_item)
            media_list.setItemWidget(media_item, entry)

        VBox = QVBoxLayout()
        VBox.addWidget(media_list)

        self.setLayout(VBox)


if __name__ == "__main__":
    MainEventHandler = QApplication([])
    MainApplication = QuickExample()
    MainApplication.show()
    sysExit(MainEventHandler.exec_())