QListView 中的复选框选择 [英] Checkbox selection in QListView

查看:90
本文介绍了QListView 中的复选框选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了一个带有复选框的简单对话框,它允许用户从列表中选择一个或多个项目.除了标准的 OK 和 Cancel 按钮外,它还添加了 Select All 和 Unselect All 按钮,允许用户一次选中/取消选中所有项目(这对于大列表很方便).

I developed a simple dialog with a checkbox, which allows the user to select one or several items from a list. Besides the standard OK and Cancel buttons, it adds Select All and Unselect All buttons, allowing the user to check/uncheck all items at once (this comes handy for large lists).

import os, sys
from PyQt4 import Qt, QtCore, QtGui

class ChecklistDialog(QtGui.QDialog):
    def __init__(self, name, stringlist=None, checked=False, icon=None, parent=None):
        super(ChecklistDialog, self).__init__(parent)

        self.name = name
        self.icon = icon
        self.model = QtGui.QStandardItemModel()
        self.listView = QtGui.QListView()

        if stringlist is not None:
            for i in range(len(stringlist)):
                item = QtGui.QStandardItem(stringlist[i])
                item.setCheckable(True)
                check = QtCore.Qt.Checked if checked else QtCore.Qt.Unchecked
                item.setCheckState(check)
                self.model.appendRow(item)

        self.listView.setModel(self.model)

        self.okButton = QtGui.QPushButton("OK")
        self.cancelButton = QtGui.QPushButton("Cancel")
        self.selectButton = QtGui.QPushButton("Select All")
        self.unselectButton = QtGui.QPushButton("Unselect All")

        hbox = QtGui.QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(self.okButton)
        hbox.addWidget(self.cancelButton)
        hbox.addWidget(self.selectButton)
        hbox.addWidget(self.unselectButton)

        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(self.listView)
        vbox.addStretch(1)
        vbox.addLayout(hbox)
        
        self.setLayout(vbox)    
        #self.setLayout(layout)
        self.setWindowTitle(self.name)
        if self.icon is not None: self.setWindowIcon(self.icon)

        self.okButton.clicked.connect(self.accept)
        self.cancelButton.clicked.connect(self.reject)
        self.selectButton.clicked.connect(self.select)
        self.unselectButton.clicked.connect(self.unselect)
        
    def reject(self):
        QtGui.QDialog.reject(self)

    def accept(self):
        self.choices = []
        i = 0
        while self.model.item(i):
            if self.model.item(i).checkState():
                self.choices.append(self.model.item(i).text())
            i += 1
        QtGui.QDialog.accept(self)
        
    def select(self):
        i = 0
        while self.model.item(i):
            item = self.model.item(i)
            if not item.checkState():
                item.setCheckState(True)
            i += 1
        
    def unselect(self):
        i = 0
        while self.model.item(i):
            item = self.model.item(i)
            item.setCheckState(False)
            i += 1  

if __name__ == "__main__":
    fruits = ["Banana", "Apple", "Elderberry", "Clementine", "Fig",
        "Guava", "Mango", "Honeydew Melon", "Date", "Watermelon",
        "Tangerine", "Ugli Fruit", "Juniperberry", "Kiwi", "Lemon",
        "Nectarine", "Plum", "Raspberry", "Strawberry", "Orange"]
    app = QtGui.QApplication(sys.argv)
    form = ChecklistDialog("Fruit", fruits, checked=True)
    if form.exec_():
        print("\n".join([str(s) for s in form.choices]))

上面的代码有效,但我对 QListView 的奇怪行为感到困扰:当对话框显示为检查"时参数变为 True,所有复选框都显示为带有X"的选中状态;标记(如预期).但是,当单击全选"按钮时,复选框变为灰色(尽管正确选择了项目).我希望它们以X"显示.标记,以便向用户呈现一致的外观.

The above code works, but I am bothered by the strange behaviour of QListView: when the dialog is display with the "check" parameter turned to True, all checkbozes appear selected with an "X" mark (as expected). However, when the Select All button is clicked, the checkboxes are instead grayed (although the items are correctly selected). I would prefer that they be displayed with an "X" mark, in order to present a consistent appearance to the user.

见下图.

一般来说,我的问题是:如何控制复选框在 QListView 中的显示方式?

In general terms, my question is: how to control the way the checkboxes are displayed in a QListView?

推荐答案

问题是因为QCheckBox 的 rel="nofollow noreferrer">states 是 3:

The problem is caused because the states of a QCheckBox are 3:

Qt::Unchecked 0 项目未选中.

Qt::PartiallyChecked 1 项目被部分检查.项目在分层模型可能会被部分检查,如果一些,但不是全部,他们的孩子接受了检查.

Qt::PartiallyChecked 1 The item is partially checked. Items in hierarchical models may be partially checked if some, but not all, of their children are checked.

Qt::Checked 2 项目被选中.

正如你所看到的,它们是整数值,当你传递 True 的值时,它被转换为 1,相当于 Qt::PartiallyChecked 那些你得到矩形而不是十字的人.

And as you see they are integer values, and when you pass the value of True this is converted to 1 which is equivalent to Qt::PartiallyChecked by those you get the rectangle instead of the cross.

解决方案是将正确的值传递给它:QtCore.Qt.Checked,如下所示:

The solution is to pass it the correct value: QtCore.Qt.Checked as I show below:

import sys
from PyQt4 import Qt, QtCore, QtGui


class ChecklistDialog(QtGui.QDialog):

    def __init__(
        self,
        name,
        stringlist=None,
        checked=False,
        icon=None,
        parent=None,
        ):
        super(ChecklistDialog, self).__init__(parent)

        self.name = name
        self.icon = icon
        self.model = QtGui.QStandardItemModel()
        self.listView = QtGui.QListView()

        for string in stringlist:
            item = QtGui.QStandardItem(string)
            item.setCheckable(True)
            check = \
                (QtCore.Qt.Checked if checked else QtCore.Qt.Unchecked)
            item.setCheckState(check)
            self.model.appendRow(item)

        self.listView.setModel(self.model)

        self.okButton = QtGui.QPushButton('OK')
        self.cancelButton = QtGui.QPushButton('Cancel')
        self.selectButton = QtGui.QPushButton('Select All')
        self.unselectButton = QtGui.QPushButton('Unselect All')

        hbox = QtGui.QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(self.okButton)
        hbox.addWidget(self.cancelButton)
        hbox.addWidget(self.selectButton)
        hbox.addWidget(self.unselectButton)

        vbox = QtGui.QVBoxLayout(self)
        vbox.addWidget(self.listView)
        vbox.addStretch(1)
        vbox.addLayout(hbox)

        self.setWindowTitle(self.name)
        if self.icon:
            self.setWindowIcon(self.icon)

        self.okButton.clicked.connect(self.onAccepted)
        self.cancelButton.clicked.connect(self.reject)
        self.selectButton.clicked.connect(self.select)
        self.unselectButton.clicked.connect(self.unselect)

    def onAccepted(self):
        self.choices = [self.model.item(i).text() for i in
                        range(self.model.rowCount())
                        if self.model.item(i).checkState()
                        == QtCore.Qt.Checked]
        self.accept()

    def select(self):
        for i in range(self.model.rowCount()):
            item = self.model.item(i)
            item.setCheckState(QtCore.Qt.Checked)

    def unselect(self):
        for i in range(self.model.rowCount()):
            item = self.model.item(i)
            item.setCheckState(QtCore.Qt.Unchecked)


if __name__ == '__main__':
    fruits = [
        'Banana',
        'Apple',
        'Elderberry',
        'Clementine',
        'Fig',
        'Guava',
        'Mango',
        'Honeydew Melon',
        'Date',
        'Watermelon',
        'Tangerine',
        'Ugli Fruit',
        'Juniperberry',
        'Kiwi',
        'Lemon',
        'Nectarine',
        'Plum',
        'Raspberry',
        'Strawberry',
        'Orange',
        ]
    app = QtGui.QApplication(sys.argv)
    form = ChecklistDialog('Fruit', fruits, checked=True)
    if form.exec_() == QtGui.QDialog.Accepted:
        print '\n'.join([str(s) for s in form.choices])

这篇关于QListView 中的复选框选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆