PyQt:如何获得大部分 QListWidget

Posted

技术标签:

【中文标题】PyQt:如何获得大部分 QListWidget【英文标题】:PyQt: How to get most of QListWidget 【发布时间】:2014-04-24 16:53:20 【问题描述】:

代码构建了一个带有单个 QListWidget 和单个 QPushButton 的对话框。

单击按钮会添加一个列表项。

右键单击列表项会弹出一个右键菜单,其中包含可用的“删除项”命令。

选择“移除项目”命令会从列表小部件中移除一个列表项目。

看看如何实现以下 ListWidgets 操作会很有趣:

    能够上下移动列表项(重新排列)。 能够多选和多删除列表项。 更好更健壮的列表项排序。

示例:

import sys, os
from PyQt4 import QtCore, QtGui    

class ThumbListWidget(QtGui.QListWidget):
    def __init__(self, type, parent=None):
        super(ThumbListWidget, self).__init__(parent)
        self.setAcceptDrops(True)
        self.setIconSize(QtCore.QSize(124, 124))

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls:
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls:
            event.setDropAction(QtCore.Qt.CopyAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls:
            event.setDropAction(QtCore.Qt.CopyAction)
            event.accept()
            links = []
            for url in event.mimeData().urls():
                links.append(str(url.toLocalFile()))
            self.emit(QtCore.SIGNAL("dropped"), links)
        else:
            event.ignore()

class Dialog_01(QtGui.QMainWindow):
    def __init__(self):
        super(QtGui.QMainWindow,self).__init__()
        self.listItems=

        myQWidget = QtGui.QWidget()
        myBoxLayout = QtGui.QVBoxLayout()
        myQWidget.setLayout(myBoxLayout)
        self.setCentralWidget(myQWidget)

        self.myListWidget = ThumbListWidget(self)  
        self.myListWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.myListWidget.connect(self.myListWidget, QtCore.SIGNAL("customContextMenuRequested(QPoint)" ), self.listItemRightClicked)

        myButton = QtGui.QPushButton("Add List Item")

        myBoxLayout.addWidget(self.myListWidget)
        myBoxLayout.addWidget(myButton)
        myButton.clicked.connect(self.addListWidgetItem)                

    def addListWidgetItem(self):
        listItemName='Item '+str(len(self.listItems.keys()))        
        self.listItems[listItemName]=None
        self.rebuildListWidget() 

    def listItemRightClicked(self, QPos): 
        self.listMenu= QtGui.QMenu()
        menu_item = self.listMenu.addAction("Remove Item")
        if len(self.listItems.keys())==0: menu_item.setDisabled(True)
        self.connect(menu_item, QtCore.SIGNAL("triggered()"), self.menuItemClicked) 

        parentPosition = self.myListWidget.mapToGlobal(QtCore.QPoint(0, 0))        
        self.listMenu.move(parentPosition + QPos)

        self.listMenu.show() 

    def menuItemClicked(self):
        if len(self.listItems.keys())==0: print 'return from menuItemClicked'; return
        currentItemName=str(self.myListWidget.currentItem().text() )
        self.listItems.pop(currentItemName, None)
        self.rebuildListWidget()

    def rebuildListWidget(self):
        self.myListWidget.clear()
        items=self.listItems.keys()
        if len(items)>1: items.sort()
        for listItemName in items:
            listItem = QtGui.QListWidgetItem( listItemName, self.myListWidget )
            self.listItems[listItemName]=listItem


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    dialog_1 = Dialog_01()
    dialog_1.show()
    dialog_1.resize(480,320)
    sys.exit(app.exec_())

【问题讨论】:

根据我的经验,当您必须处理插入、删除、排序、排序等操作时,使用QListView(基于视图模型)通常比QListWidget(基于项目)。 QAbstractItemModel 拥有排序、插入等所需的所有插槽。 关于第 3 项:“更好”和“更健壮”是什么意思? 就像现在一样,sort() 以时尚的方式列出字符串,例如:'Item 2'、'Item 20'、'Item 3'、'Item 4' end 等。后面没有逻辑这个简单的字符串排序。其次,在 self.listItems 字典中排序的 listItem 名称及其 QT 对象不允许创建两个或多个具有相同名称的列表项,因为它们用作字典键。我想知道是否还有其他更好更“流行”的方式来做到这一点......因为我在这里使用它的方式完全是我的想法。 排序是按字母顺序排列且不区分大小写,这似乎是一个合理(且合乎逻辑)的默认设置。我不明白您示例中 listItems dict 或 rebuildListWidget 方法的目的,这两者似乎都是多余的。 看看如何以不同的方式完成会很有趣!发布吧! 【参考方案1】:

列表小部件项目可以通过拖放上下移动,但默认情况下不启用。要打开它,请执行以下操作:

    self.listWidget.setDragDropMode(QtGui.QAbstractItemView.InternalMove)

多选是几个可用的selection-modes 之一。要打开它,请执行以下操作:

    self.listWidget.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)

默认情况下禁用排序。要打开它,请执行以下操作:

    self.listWidget.setSortingEnabled(True)

要重新排序列表,请执行以下操作之一:

    self.listWidget.sortItems() # ascending by default
    self.listWidget.sortItems(QtCore.Qt.DescendingOrder)

默认情况下,排序是按字母顺序和不区分大小写的。如果您想要自定义排序顺序,子类QListWidgetItem 并重新实现其小于运算符:

class ListWidgetItem(QtGui.QListWidgetItem):
    def __lt__(self, other):
        return self.text() < other.text() # or whatever

【讨论】:

以上是关于PyQt:如何获得大部分 QListWidget的主要内容,如果未能解决你的问题,请参考以下文章

我如何获得 PyQt4.phonon?

PyCharm / PyQt:如何通过动态加载的 ui 文件获得代码补全

python PyQt4中如何获得QTextEdit的内容获得QLineEdit的内容有QLineEdit.text(),那QTextEdit呢?

如何从 Python 日志记录模块获得非阻塞/实时行为? (输出到 PyQt QTextBrowser)

如何在 PyQt5 InputDialog 中获取更多输入文本?

在qlineedit获得文本后如何删除空格?