在 QListWidget 中使用自定义 QListWidgetItems

Posted

技术标签:

【中文标题】在 QListWidget 中使用自定义 QListWidgetItems【英文标题】:use custom QListWidgetItems in QListWidget 【发布时间】:2020-10-06 09:28:23 【问题描述】:

嘿,我想在我的 QListWidget 中使用自定义 QListWidgetItems,但我根本无法显示它。

我希望 QListWidgetItem 看起来像这样:

这是我的代码:

from PySide2 import QtWidgets, QtCore, QtGui
from PySide2.QtCore import QSize
from PySide2.QtGui import QKeySequence, QFont, QPixmap, QWindow
from PySide2.QtWidgets import QShortcut, QLabel
from maya import OpenMayaUI
import maya.cmds as cmds
import sys

try:
    from shiboken import wrapInstance
    import shiboken
except:
    from shiboken2 import wrapInstance
    import shiboken2 as shiboken

allInfo = ['label' : 'Giraffe',
            'command': 'print "The giraffe runs through the desert"',
            'annotation' : 'This command tells you what the giraffe is doing.',
            'image': '',
            'menu': '',

            'label' : 'Dragon',
            'command': 'print "The dragon flies towards the divine sky."',
            'annotation' : 'This command tells you what the dragon is doing.',
            'image': '',
            'menu': '',

            'label' : 'Dog',
            'command': 'print "The dog barks at the neighbor."',
            'annotation' : 'This command tells you what the dog is doing.',
            'image': '',
            'menu': '',

            'label' : 'Cat',
            'command': 'print "The cat does give a damn."',
            'annotation' : 'This command tells you what the cat is doing.',
            'image': '',
            'menu': '',

            'label' : 'Bull',
            'command': 'print "The bull runs towards the bullfighter"',
            'annotation' : 'This command tells you what the bull is doing.',
            'image': '',
            'menu': '',

            'label' : 'Ferret',
            'command': 'print "The ferret plays with the master."',
            'annotation' : 'This command tells you what the ferret is doing.',
            'image': '',
            'menu': '',

            'label' : 'Monkey',
            'command': 'print "The monkey is looking for bananas."',
            'annotation' : 'This command tells you what the monkey is doing.',
            'image': '',
            'menu': '',

            'label' : 'Bear',
            'command': 'print "The bear is looking for salmons."',
            'annotation' : 'This command tells you what the bear is doing.',
            'image': '',
            'menu': '',

            'label' : 'Ferret',
            'command': 'print "The ferret plays with the master."',
            'annotation' : 'This command tells you what the ferret is doing.',
            'image': '',
            'menu': '',

            'label' : 'Tiger',
            'command': 'print "The tiger tries to look like a cute cat.."',
            'annotation' : 'This command tells you what the tiger is doing.',
            'image': '',
            'menu': '',

            'label' : 'Lama',
            'command': 'print "The lama is spitting in your face."',
            'annotation' : 'This command tells you what the lama is doing.',
            'image': '',
            'menu': '',

            'label' : 'Lion',
            'command': 'print "The lion is looking for its prey."',
            'annotation' : 'This command tells you what the lion is doing.',
            'image': '',
            'menu': '',

            'label' : 'Fish',
            'command': 'print "The fish say blub."',
            'annotation' : 'This command tells you what the fish is doing.',
            'image': '',
            'menu': '',

            'label' : 'Panda',
            'command': 'print "The panda eats some bamboo."',
            'annotation' : 'This command tells you what the bamboo is doing.',
            'image': '',
            'menu': '']


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent = None):
        window = OpenMayaUI.MQtUtil.mainWindow()
        mayaWindow = shiboken.wrapInstance(long(window), QtWidgets.QMainWindow)
        super(MainWindow, self).__init__(mayaWindow)

        self.setWindowTitle('Test Window')
        self.resize(630, 400)
        self._window = None

        # main widget
        mainWidget = QtWidgets.QWidget(self)
        self.setCentralWidget(mainWidget)

        # layout initialize
        self.mainLayout = QtWidgets.QVBoxLayout()
        self.HBoxLayout = QtWidgets.QHBoxLayout()
        self.VBoxLayout = QtWidgets.QVBoxLayout()
        self.mainLayout.addLayout(self.VBoxLayout)
        self.VBoxLayout.addLayout(self.HBoxLayout)
        mainWidget.setLayout(self.mainLayout)

        # Add Widgets
        self.textField = QtWidgets.QLineEdit()
        self.textField.textChanged.connect(self.onTextChanged)

        self.listView = QtWidgets.QListWidget()
        self.listView.setMouseTracking(True)
        self.listView.itemDoubleClicked.connect(self.runCommand)

        self.HBoxLayout.addWidget(self.textField)
        self.VBoxLayout.addWidget(self.listView)
        self.textField.setFocus()

    def onTextChanged(self):
        self.searchForCommands()

    def runCommand(self):
        index = self.listView.currentRow()
        input = self.textField.text()
        if input == '' or input.isspace() or input == ' ' or input == None:
            item = None
        else:
            try:
                item = self.listView.item(index).text()
            except(AttributeError):
                item = None
        if item != None:
            if allInfo != None:
                ExecuteCommand(item, input)

    def showWindow(self):
        self.closeWindow()
        if self._window is None:
            self._window = MainWindow()
            self._window.show()

    def closeWindow(self):
        self.close()

    def searchForCommands(self):        
        maxListLength = 20
        input = self.textField.text().lower()
        if input == '' or input.isspace() or input == ' ' or input == None:
            if self.listView.count() > 0:
                self.listView.clear()
        else:
            if self.listView.count() > 0:
                self.listView.clear()
            i = 0
            for x in range(len(allInfo)):
                if i < maxListLength:
                    label = allInfo[x].get('label')
                    if input in label.lower():
                        item = QtWidgets.QListWidgetItem(label)
                        #item = ListWidgetItem()
                        #item.SetIcon('')
                        #item.SetMenu('test menu')
                        #item.SetName(label)
                        #item.SetAnnotation('Test annotation.')
                        self.listView.addItem(item)
                        i += 1
                        continue
                    else:
                        pass
            self.listView.setCurrentRow(0)


class ListWidgetItem(QtWidgets.QListWidgetItem):
    def __init__(self):
        super(ListWidgetItem, self).__init__()
        self.mainHBoxLayout = QtWidgets.QHBoxLayout()
        self.iconLabel = QtWidgets.QLabel()
        self.mainHBoxLayout.addWidget(self.iconLabel)

        self.rightVBoxLayout = QtWidgets.QVBoxLayout()
        self.menuNameHBoxLayout = QtWidgets.QHBoxLayout()
        self.rightVBoxLayout.addLayout(self.menuNameHBoxLayout)

        self.nameLabel = QtWidgets.QLabel()
        self.annotationLabel = QtWidgets.QLabel()
        self.menuLabel = QtWidgets.QLabel()
        self.menuNameHBoxLayout.addWidget(self.menuLabel)
        self.menuNameHBoxLayout.addWidget(self.nameLabel)
        self.rightVBoxLayout.addWidget(self.annotationLabel)

    def SetName(self, text):
        self.nameLabel.setText(text)

    def SetAnnotation(self, text):
        self.annotationLabel.setText(text)

    def SetIcon(self, iconPath = ''):
        self.iconLabel.setPixmap(QtGui.QPixmap(iconPath))

    def SetMenu(self, text):
        self.menuLabel.setText(text)


def startApp(*args):
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.showWindow()

def ExecuteCommand(listViewSelection, input, *args):
    ranCommand = False
    for x in range(len(allInfo)):
        if not ranCommand:
            if listViewSelection != None:
                label = allInfo[x].get('label')
                command = allInfo[x].get('command')
                if label == listViewSelection:
                    RunCommand(command)
                    ranCommand = True
        else:
            break

def RunCommand(command):
    cmds.evalDeferred(command)

if __name__ == '__main__':
    if not cmds.about(batch = True):
        startApp()

第 190 行 searchForCommand 下被注释掉的部分是我尝试添加我在脚本中编写的自定义 QListWidgetItem 类,但它不起作用。

那么如何让它工作,使 QListWidgetItems 看起来像所附图片中的那样?该脚本在 Maya2020 中运行良好,只需在脚本编辑器中运行它,您必须双击 QListWidgetItem 才能运行它的命令。 ListWidgetItem 类是我试图让它工作的尝试。

【问题讨论】:

【参考方案1】:

也许您可以考虑将 setItemWidget() 与常规 QListWidgetItem 一起使用。

例如:

...

    def searchForCommands(self):        
        maxListLength = 20
        input = self.textField.text().lower()
        if input == '' or input.isspace() or input == ' ' or input == None:
            if self.listView.count() > 0:
                self.listView.clear()
        else:
            if self.listView.count() > 0:
                self.listView.clear()
            i = 0
            for x in range(len(allInfo)):
                if i < maxListLength:
                    label = allInfo[x].get('label')
                    if input in label.lower():
                        
                        itemWidget = ListWidgetItem()
                        itemWidget.SetIcon('')
                        itemWidget.SetMenu('test menu')
                        itemWidget.SetName(label)
                        itemWidget.SetAnnotation('Test annotation.')
  
                        item = QtWidgets.QListWidgetItem(label)
                        item.setSizeHint(itemWidget.sizeHint())
                        
                        self.listView.addItem(item)
                        self.listView.setItemWidget(item, itemWidget)
                        i += 1
                        continue
                    else:
                        pass
            self.listView.setCurrentRow(0)


class ListWidgetItem(QtWidgets.QWidget):
    def __init__(self):
        super(ListWidgetItem, self).__init__()
                
        self.mainHBoxLayout = QtWidgets.QHBoxLayout()
        self.mainHBoxLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        
        self.iconLabel = QtWidgets.QLabel(text="ICON")
        self.mainHBoxLayout.addWidget(self.iconLabel)
        
        self.rightVBoxLayout = QtWidgets.QVBoxLayout()
        self.rightVBoxLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.mainHBoxLayout.addLayout(self.rightVBoxLayout)

        self.menuNameHBoxLayout = QtWidgets.QHBoxLayout()
        self.menuNameHBoxLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)

        self.rightVBoxLayout.addLayout(self.menuNameHBoxLayout)
        self.nameLabel = QtWidgets.QLabel(text="Label")
        self.annotationLabel = QtWidgets.QLabel("Annotation")
        self.menuLabel = QtWidgets.QLabel("Menu")
        self.menuNameHBoxLayout.addWidget(self.menuLabel)
        self.menuNameHBoxLayout.addWidget(self.nameLabel)
        self.rightVBoxLayout.addWidget(self.annotationLabel)

        self.setLayout(self.mainHBoxLayout)

    def SetName(self, text):
        self.nameLabel.setText(text)

    def SetAnnotation(self, text):
        self.annotationLabel.setText(text)

    def SetIcon(self, iconPath = ''):
        self.iconLabel.setPixmap(QtGui.QPixmap(iconPath))

    def SetMenu(self, text):
        self.menuLabel.setText(text)


...

item.setSizeHint(itemWidget.sizeHint()) 是这里最重要的线路。如果你的尺寸不匹配,它根本不会起作用。

【讨论】:

以上是关于在 QListWidget 中使用自定义 QListWidgetItems的主要内容,如果未能解决你的问题,请参考以下文章

Qt - 如何从 QListWidget 中获取选定的自定义项目?

如何在 QListWidget 中缩放自定义小部件?

如何使用自定义项目小部件拖放 QListWidget 项目?

如何在自定义 QTextEdit 中接受来自 QListWidget 的拖放

在 QListWidget 之间拖放自定义小部件项目

QListWidget 拖放与通过 setItemWidget 设置的自定义小部件