不同 QListView 显示选项之间的转换(是否使用复选框)

Transition between different QListView display options (With CheckBoxes or not)

对于这个应用程序,我尝试创建 QListView 视图的 2 个变体,并应用不同的方式来处理它。第一个选项涉及一个没有复选框的列表,用户可以在按住 CTRL 键的同时 select 多个项目:Variant 1. The second option differs visually from the first - checkboxes are present, and the selection process is also different (you do not need to use CTRL, and clicking on a specific position first selects it and then deselects it)Variant 1.

#!/usr/bin/python
# coding=utf-8

headline = """ 
###############################################################################
#                                   Program                                   #
#            a small ListView application in PyQt5 (Python 3.7)               #
###############################################################################
All comments are in two languages (Russian, English)
Все комментарии на двух языках (русский, английский)
"""

import sys
import random
from PyQt5 import QtWidgets, QtGui, QtCore, Qt

class HelloApplication(QtWidgets.QApplication):
    def __init__(self, args):
        """
            In the constructor, we do everything that is necessary to run our application, which
            creates a QApplication in the __init__ method, then adds our widgets and finally
            runs exec_loop
            В конструкторе мы делаем всё, что необходимо для запуска нашего приложения, которое
            создаёт QApplication в __init__ методе, затем добавляет наши виджеты и, наконец,
            запускает exec_loop
        """
        QtWidgets.QApplication.__init__(self,args)
        self.addWidgets()

    def addWidgets(self):

    # Create widgets
    # Создание виджетов
        self.checkCalc=0
        self.StartList=[]
        self.BaseWidget=QtWidgets.QWidget()
        self.BaseWidget.setWindowTitle('Example List')
        self.grid = QtWidgets.QGridLayout()
        self.verCombo = QtWidgets.QComboBox()
        self.listView=QtWidgets.QListView()
        self.listViewmodel = QtGui.QStandardItemModel(self.listView)
        self.listView.setModel(self.listViewmodel)

    # Setting options for widgets (placement, size)
    # Установка параметров для виджетов (размещение, размеры)
        self.listView.setModelColumn(2)
        self.grid.addWidget(self.verCombo,0,0,1,3)
        self.grid.addWidget(self.listView, 2, 0, 3, 3)

    # Setting actions for widgets
    # Установка действий для виджетов
        self.listView.clicked[QtCore.QModelIndex].connect(self.on_clicked)
        self.verCombo.activated[str].connect(self.onverComboActivated)

    # Setting statuses, texts, etc. for widgets at start
    # Установка статусов, текстов и прочего для виджетов на старте
        self.verCombo.addItem("1 - NO CKECKBOXES")
        self.verCombo.addItem("2 - WITH CKECKBOXES")
        self.verCombo.setCurrentIndex(0)

    # This piece of code determines whether multiple items can be selected on a ListView.
    # Этот кусочек кода определяет, можно ли выбирать несколько элементов на ListView.
        if self.verCombo.currentIndex() + 1 == 1:
            self.listView.setSelectionMode(
                QtWidgets.QAbstractItemView.ExtendedSelection
            )
            #self.show_hide_ckeckinlistView(FType=1)
        else:
            self.listView.setSelectionMode(
                QtWidgets.QAbstractItemView.SingleSelection
            )

        self.addrowinlistView(
            'Cookie dough',  # Must be store-bought
            'Hummus',  # Must be homemade
            'Spaghetti',  # Must be saucy
            'Dal makhani',  # Must be spicy
            'Chocolate whipped cream'  # Must be plentiful
        )

        self.BaseWidget.setLayout(self.grid)
        chechAllSelected_resulr1, chechAllSelected_resulr2, chechAllSelected_resulr3, chechAllSelected_resulr4 = self.chechAllSelected()
        self.BaseWidget.show()

    # Procedure for determining those items that are highlighted
    # The procedure should work both in the situation of the list with checkmarks, and without them
    # Процедура для определения тех элементов, которые выделены
    # Процедура должна работать как в ситуации списка с галочками, так и без них
    def chechAllSelected (self):
        SelectedList=[]
        list_of_indexes_selectedLayers=[]
        list_of_texts_selectedLayers=[]
        Items_list=[]
        #item = self.listView.itemFromIndex()
        selectedLayers = self.listView.selectedIndexes()

        # CUT FOR A SHEET WITHOUT TYPES
        # ОТЛАВЛИВАЕМ ДЛЯ ЛИСТА БЕЗ ГАЛОЧЕК
        if self.verCombo.currentIndex()+1==1:
            print ("Here when checking")
            for i in selectedLayers:
                item = self.listViewmodel.itemFromIndex(i)
                Items_list.append(item)
                list_of_indexes_selectedLayers.append(item.index().row())
            list_of_indexes_selectedLayers.sort()
            for i in range(len(list_of_indexes_selectedLayers)):
                SelectedList.append(int(list_of_indexes_selectedLayers[i]))
                item = self.listViewmodel.itemFromIndex(
                    self.listViewmodel.index(int(list_of_indexes_selectedLayers[i]), 0))
                list_of_texts_selectedLayers.append(item.text())
            print("List: ", list_of_indexes_selectedLayers, " ", list_of_texts_selectedLayers, " ", Items_list)

        # CUT FOR A SHEET WITH TIPS
        # ОТЛАВЛИВАЕМ ДЛЯ ЛИСТА С ГАЛОЧКАМИ
        else:
            for i in range(self.listViewmodel.rowCount()):
                if self.listViewmodel.item(i).checkState():
                    SelectedList.append(i)
        if len(SelectedList)==0: res_chechAllSelected=0
        if 0<len(SelectedList)<self.listViewmodel.rowCount(): res_chechAllSelected=1
        if 0<len(SelectedList) == self.listViewmodel.rowCount(): res_chechAllSelected = 2

        print ("In chechAllSelected:", len(SelectedList)," ", self.listViewmodel.rowCount()," ", res_chechAllSelected, " ", SelectedList)
        return len(SelectedList), self.listViewmodel.rowCount(), res_chechAllSelected, SelectedList


    # Function for entering values in ListView (any values, lists)
    # Функция ввода значений в ListView (любые значения, списки)
    def addrowinlistView(self,*rowsforadd):
        for i in rowsforadd:
            # Create an item with a caption
            item = QtGui.QStandardItem(i)
            # Add a checkbox to it
            #item.setCheckState(True)
            # generate a list for random selection
            # генерируем список для случайного выбора
            Chous_for_random = [0, 2] 
            if self.verCombo.currentIndex() + 1 == 1:
                #print("индекс переключателя: ",self.verCombo.currentIndex() + 1)
                # whether to tick the item
                # ставить ли галочку около элемента
                item.setCheckable(False)
                self.listViewmodel.appendRow(item)
                if random.choice(Chous_for_random)==2:
                    index = self.listViewmodel.indexFromItem(item)
                    sm = self.listView.selectionModel()
                    sm.select(index, QtCore.QItemSelectionModel.Select)
            else:
                # whether to tick the item
                # ставить ли галочку около элемента
                item.setCheckable(True)
                # set the status depending on the selected number
                # ставим статус в зависимости от выбранного числа
                item.setCheckState(random.choice(Chous_for_random))
                self.listViewmodel.appendRow(item)
            # Add the item to the model
            # Добавляем элемент в модель
            #self.listViewmodel.appendRow(item)
            #self.BaseWidget.listViewmodel.appendRow(item)

    def on_clicked(self, index):
        item = self.listViewmodel.itemFromIndex(index)
        myitem=QtWidgets.QListWidgetItem()
        #print (("on_clicked: itemIndex='{}', itemText='{}'"
        #        .format(item.index().row(), item.text())))
        if self.verCombo.currentIndex()+1==1:
            # print(item.index().row())
            pass
        else:
            print("""This position: """, int(item.index().row()))
            chechAllSelected_resulr1, chechAllSelected_resulr2, chechAllSelected_resulr3, chechAllSelected_resulr4 = self.chechAllSelected()
            self.StartList = chechAllSelected_resulr4
            if self.listViewmodel.item(item.index().row()).checkState():
                item.setCheckState(0)
                self.StartList.remove(item.index().row())
            else:
                item.setCheckState(2)
                self.StartList.append(item.index().row())
        print("Here")
        chechAllSelected_resulr1, chechAllSelected_resulr2, chechAllSelected_resulr3, chechAllSelected_resulr4 = self.chechAllSelected()
        #print("Here")
        #self.on_chechBox_click(FType=False, FClick=0, FStatus=chechAllSelected_resulr3)
        #self.chechAllSelected()
        #self.listViewmodel.removeRow(item.index().row())

    # mode switching (with / without checkmarks) with the removal of the function to remove / show checkmarks
    # перевлючение режима (с галочками / без) с вывозом функции убрать / показать галочки
    def onverComboActivated(self, text):
        self.verCombo.setCurrentText(text)
        len_SelectedList, listViewmodel_rowCount, res_chechAllSelected, SelectedLis = self.chechAllSelected()
        print ("This point: ", len_SelectedList," ", listViewmodel_rowCount," ", res_chechAllSelected," ", SelectedLis)
        self.show_hide_ckeckinlistView(
            self.verCombo.currentIndex(),
            listViewmodel_rowCount,
            SelectedLis
        )
        print(self.verCombo.currentText())

        # print(self.verCombo.currentText()," индекс = ", self.verCombo.currentIndex())
        # self.chechAllSelected ()

if __name__ == "__main__":
    app = HelloApplication(sys.argv)
    sys.exit(app.exec_())

QAbstractItemView Class

selectionMode : SelectionMode

This property holds which selection mode the view operates in This property controls whether the user can select one or many items and, in many-item selections, whether the selection must be a continuous range of items.


QAbstractItemView::ExtendedSelection

When the user selects an item in the usual way, the selection is cleared and the new item selected. However, if the user presses the Ctrl key when clicking on an item, the clicked item gets toggled and all other items are left untouched. If the user presses the Shift key while clicking on an item, all items between the current item and the clicked item are selected or unselected, depending on the state of the clicked item. Multiple items can be selected by dragging the mouse over them.

试一试:

headline = """ 
###############################################################################
#                                    Program                                  #
#                     a small ListView application in PyQt                    #
###############################################################################
"""

import sys
import random
from PyQt5 import QtWidgets, QtGui, QtCore                    #  , Qt

class HelloApplication(QtWidgets.QWidget):                    #QApplication):
    def __init__(self):
        super().__init__()
        self.addWidgets()

    def addWidgets(self):
        self.checkCalc  = 0
        self.StartList  = []
#        self.BaseWidget = QtWidgets.QWidget()
        self.setWindowTitle('Example List')
        
        self.grid = QtWidgets.QGridLayout()
        self.verCombo = QtWidgets.QComboBox()
        self.listView = QtWidgets.QListView()
        
# +++   
        self.listView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)     # +++
        
        self.listViewmodel = QtGui.QStandardItemModel(self.listView)
        self.listView.setModel(self.listViewmodel)

        self.listView.setModelColumn(2)
        self.grid.addWidget(self.verCombo, 0, 0, 1, 3)
        self.grid.addWidget(self.listView, 2, 0, 3, 3)

        self.listView.clicked[QtCore.QModelIndex].connect(self.on_clicked)
        self.verCombo.activated[str].connect(self.onverComboActivated)

        self.verCombo.addItem("1 - NO edit CKECKBOXES")
        self.verCombo.addItem("2 - WITH edit CKECKBOXES")
        self.verCombo.setCurrentIndex(0)

        self.addrowinlistView(
            'Cookie dough',            # Must be store-bought
            'Hummus',                  # Must be homemade
            'Spaghetti',               # Must be saucy
            'Dal makhani',             # Must be spicy
            'Chocolate whipped cream'  # Must be plentiful
        )

        self.setLayout(self.grid)
        
        chechAllSelected_resulr1, \
        chechAllSelected_resulr2, \
        chechAllSelected_resulr3, \
        chechAllSelected_resulr4 = self.chechAllSelected()


    def chechAllSelected (self):
        SelectedList = []
        list_of_indexes_selectedLayers = []
        list_of_texts_selectedLayers = []
        Items_list = []
        #item = self.listView.itemFromIndex()
        selectedLayers = self.listView.selectedIndexes()

        if self.verCombo.currentIndex()+1 == 1:
            print ("Here for check")
            for i in selectedLayers:
                item = self.listViewmodel.itemFromIndex(i)
                Items_list.append(item)
                list_of_indexes_selectedLayers.append(item.index().row())
            list_of_indexes_selectedLayers.sort()
            for i in range(len(list_of_indexes_selectedLayers)):
                SelectedList.append(int(list_of_indexes_selectedLayers[i]))
                item = self.listViewmodel.itemFromIndex(
                    self.listViewmodel.index(int(list_of_indexes_selectedLayers[i]), 0))
                list_of_texts_selectedLayers.append(item.text())
            print("List: ", list_of_indexes_selectedLayers, " ", list_of_texts_selectedLayers, " ", Items_list)

        else:
            for i in range(self.listViewmodel.rowCount()):
                if self.listViewmodel.item(i).checkState():
                    SelectedList.append(i)
        if len(SelectedList)==0:                                 res_chechAllSelected = 0
        if 0<len(SelectedList)<self.listViewmodel.rowCount():    res_chechAllSelected = 1
        if 0<len(SelectedList) == self.listViewmodel.rowCount(): res_chechAllSelected = 2

        print ("В модуле chechAllSelected:", len(SelectedList)," ", self.listViewmodel.rowCount()," ", res_chechAllSelected, " ", SelectedList)

        return len(SelectedList), self.listViewmodel.rowCount(), res_chechAllSelected, SelectedList


    def addrowinlistView(self, *rowsforadd):
        for i in rowsforadd:
            # Create an item with a caption
            item = QtGui.QStandardItem(i)
            # Add a checkbox to it
           
            item.setCheckState(True)                                               # +
            
            Chous_for_random = [0, 2]
            if self.verCombo.currentIndex() + 1 == 1:
                #print("индекс переключателя: ",self.verCombo.currentIndex() + 1)
                item.setCheckable(False)
                self.listViewmodel.appendRow(item)
                if random.choice(Chous_for_random)==2:
                    index = self.listViewmodel.indexFromItem(item)
                    sm = self.listView.selectionModel()
                    sm.select(index, QtCore.QItemSelectionModel.Select)
            else:
                item.setCheckable(True)
                item.setCheckState(random.choice(Chous_for_random))
                self.listViewmodel.appendRow(item)
                # Add the item to the model
            #self.listViewmodel.appendRow(item)
            #self.BaseWidget.listViewmodel.appendRow(item)

    def on_clicked(self, index):
        item   = self.listViewmodel.itemFromIndex(index)
        print(f"\nitem={item.text()}, index={index.row()}\n" )
        myitem = QtWidgets.QListWidgetItem()
        #print (("on_clicked: itemIndex='{}', itemText='{}'"
        #        .format(item.index().row(), item.text())))
        if self.verCombo.currentIndex()+1 == 1:
            # print(item.index().row())
            pass
        else:
            print("This position: ", int(item.index().row()))
            chechAllSelected_resulr1, chechAllSelected_resulr2, chechAllSelected_resulr3, chechAllSelected_resulr4 = self.chechAllSelected()
            self.StartList = chechAllSelected_resulr4
            if self.listViewmodel.item(item.index().row()).checkState():
                item.setCheckState(0)
                self.StartList.remove(item.index().row())
            else:
                item.setCheckState(2)
                self.StartList.append(item.index().row())
        print("Now here")
        chechAllSelected_resulr1, chechAllSelected_resulr2, chechAllSelected_resulr3, chechAllSelected_resulr4 = self.chechAllSelected()
        #print("Now here")
        #self.on_chechBox_click(FType=False, FClick=0, FStatus=chechAllSelected_resulr3)
        #self.chechAllSelected()
        #self.listViewmodel.removeRow(item.index().row())

    def onverComboActivated(self, text):
        self.verCombo.setCurrentText(text)
        len_SelectedList, listViewmodel_rowCount, res_chechAllSelected, SelectedLis = self.chechAllSelected()
        print ("\nFor print: \n\tlen_SelectedList = {}; \n\tlistViewmodel_rowCount = {};\
                \n\tres_chechAllSelected = {}; \n\tSelectedLis = {}" 
               "".format(len_SelectedList, listViewmodel_rowCount, res_chechAllSelected, SelectedLis))

# ?        self.show_hide_ckeckinlistView(
#            self.verCombo.currentIndex(),
#            listViewmodel_rowCount,
#            SelectedLis
#        )
        
        print(self.verCombo.currentText())

        # print(self.verCombo.currentText()," индекс = ", self.verCombo.currentIndex())
        # self.chechAllSelected ()

    """ ??????????????????????????????????????????????????
    def on_clicked(self, index):
        item = self.listViewmodel.itemFromIndex(index)
        myitem=QtWidgets.QListWidgetItem()
        #print (("on_clicked: itemIndex='{}', itemText='{}'"
        #        .format(item.index().row(), item.text())))
        if self.verCombo.currentIndex()+1==1:
            # print(item.index().row())
            pass
        else:
            print("This position: ", int(item.index().row()))
            chechAllSelected_resulr1, chechAllSelected_resulr2, chechAllSelected_resulr3, chechAllSelected_resulr4 = self.chechAllSelected()
            self.StartList = chechAllSelected_resulr4
            if self.listViewmodel.item(item.index().row()).checkState():
                item.setCheckState(0)
                self.StartList.remove(item.index().row())
            else:
                item.setCheckState(2)
                self.StartList.append(item.index().row())
        print("Now here")
        #chechAllSelected_resulr1, chechAllSelected_resulr2, chechAllSelected_resulr3, chechAllSelected_resulr4 = self.chechAllSelected()
        print("Now here")
        #self.on_chechBox_click(FType=False, FClick=0, FStatus=chechAllSelected_resulr3)
        #self.chechAllSelected()
        #self.listViewmodel.removeRow(item.index().row())
    """

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    w = HelloApplication()
    w.show()
    sys.exit(app.exec_())