Search code examples
pythonpyqtpyqt5qmainwindowqlistwidget

QlistWidget - list with multiple signals/connections?


I am building simple GUI for my own tasks. Is it possible to make QlistWidget or something like this with multiple signals/connections? Couldnt find good way to assign multiple signals to multiple elements on list.

What I need is something like list (with checkboxes).

  • Every single element on list should do different assigned tasks.
  • I can mark for example 3 checkboxes
  • After pressing button - do tasks for marked elements on list.

my gui

# -- coding: utf-8 --

from PyQt5.QtWidgets import QMainWindow,QAction,QListWidget, qApp, QGridLayout, QWidget, QDesktopWidget,QPushButton, QTextEdit,QListView,QTreeView,QListWidgetItem
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, pyqtSignal
import qdarkstyle

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow,self).__init__(parent)

        self.main_frame()
        self.center() #center frame
        self.layout_init() #widgets layout

    def main_frame(self):
        ### actions on meenubar
        exitAct = QAction(QIcon('exit.png'), '&Exit', self)
        exitAct.setShortcut('Ctrl+Q')
        exitAct.setStatusTip('Exit application')
        exitAct.triggered.connect(qApp.quit)
        self.statusBar()

        ### menubar
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAct)
        fileMenu = menubar.addMenu('&VIew')
        fileMenu = menubar.addMenu('&Help')

        ### basic geometry and color
        self.setWindowTitle('DIGITAL CARE - Data Processing - WAREX Checklist')
        self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))

    def layout_init(self):
        grid = QGridLayout()
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        ### widgets
        pb = QPushButton(self.tr("Run process"))
        te = QTextEdit()
        test = QTextEdit()

        ### List withc checkboxes
        checklist = ["Pliki z Errorami","Fatal w Komponentach","Play - automat do Aktywacji","Play - maile przy Dezaktywacji",\
                     "Play - komunikaty Dezaktywacyjne","Automat do przedłużania polis",\
                     "X-KOM - ilość polis","Neonet - ilość polis","Satysfakcja - ilość polis","PLK - zaczytanie plików do bazy"]

        doubleClicked = pyqtSignal()

        ## Select all/unselect all
        model = QListWidget()
        selectall = QListWidgetItem("Select all")
        model.addItem(selectall)

        for i in checklist:
            item = QListWidgetItem(i)
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)
            model.addItem(item)

        #selectall.itemClicked.connect(self.select_unselectall)
        #model.itemDoubleClicked.connect(self.select_unselectall)
        #model.currentItemChanged.connect(self.select_unselectall
        #model.itemDoubleClicked.connect(self.select_unselectall) doubleclick

        #for element in range(model.count()):
           # print(model.item(element).text())
            #print(model.itemActivated.connect(self.select_unselectall))
            #if model.itemActivated.emit(model.currentItem()) == selectall:

        if model.itemClicked.emit(selectall) == "Select all":
            model.itemActivated.connect(self.select_unselectall)
                #model.itemActivated.emit(self.)

        ### make vidgets alive
        self.centralWidget().setLayout(grid)
        grid.addWidget(model, 0, 0)
        grid.addWidget(te, 0, 1)
        grid.addWidget(pb, 1, 1)
        grid.addWidget(test, 1, 0)

    def select_unselectall(self, item):
        print(item.text())
        #for index in range(self.model.count()):
            #if self.model.item(index).checkState() == Qt.Checked:
               # self.model.item(index).setCheckState(Qt.Unchecked)

    def center(self):
        ###center main window
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        qr.moveCenter(cp)
        self.move(qr.topLeft())

Solution

  • You have 2 types of tasks, when you press select all you must select everything, but when the button is pressed the task is to filter the elements that are checked, in the following example I show how to do it through the clicked and itemClicked signals of QPushButton and QListWidget, respectively, you should not emit the signal but listen to it.

    from PyQt5 import QtCore, QtGui, QtWidgets
    import qdarkstyle
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow,self).__init__(parent)
    
            self.main_frame()
            self.center() #center frame
            self.layout_init() #widgets layout
    
        def main_frame(self):
            ### actions on meenubar
            exitAct = QtWidgets.QAction(QtGui.QIcon('exit.png'), '&Exit', self)
            exitAct.setShortcut('Ctrl+Q')
            exitAct.setStatusTip('Exit application')
            exitAct.triggered.connect(self.close)
            self.statusBar()
    
            ### menubar
            menubar = self.menuBar()
            fileMenu = menubar.addMenu('&File')
            fileMenu.addAction(exitAct)
            fileMenu = menubar.addMenu('&VIew')
            fileMenu = menubar.addMenu('&Help')
    
            ### basic geometry and color
            self.setWindowTitle('DIGITAL CARE - Data Processing - WAREX Checklist')
            self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))
    
        def layout_init(self):
            central_widget = QtWidgets.QWidget()
            self.setCentralWidget(central_widget)
    
            ### widgets
            pb = QtWidgets.QPushButton(self.tr("Run process"))
            pb.clicked.connect(self.on_clicked)
            ### List withc checkboxes
            checklist = ["Pliki z Errorami","Fatal w Komponentach","Play - automat do Aktywacji","Play - maile przy Dezaktywacji",\
                         "Play - komunikaty Dezaktywacyjne","Automat do przedłużania polis",\
                         "X-KOM - ilość polis","Neonet - ilość polis","Satysfakcja - ilość polis","PLK - zaczytanie plików do bazy"]
    
            ## Select all/unselect all
            self.list_widget = QtWidgets.QListWidget()
            self.list_widget.itemClicked.connect(self.on_itemClicked)
            selectall = QtWidgets.QListWidgetItem("Select all")
            self.list_widget.addItem(selectall)
    
            for i in checklist:
                item = QtWidgets.QListWidgetItem(i)
                item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
                item.setCheckState(QtCore.Qt.Unchecked)
                self.list_widget.addItem(item)
    
            grid = QtWidgets.QGridLayout(central_widget)
            grid.addWidget(pb)
            grid.addWidget(self.list_widget)
    
        @QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
        def on_itemClicked(self, item):
            if item.text() == "Select all":
                for row in range(1, self.list_widget.count()):
                    it = self.list_widget.item(row)
                    it.setCheckState(QtCore.Qt.Checked)
    
        @QtCore.pyqtSlot()
        def on_clicked(self):
            for row in range(1, self.list_widget.count()):
                it = self.list_widget.item(row)
                if it.checkState() == QtCore.Qt.Checked:
                    print(it.text())
    
        def center(self):
            qr = self.frameGeometry()
            cp = QtWidgets.QDesktopWidget().availableGeometry().center()
            qr.moveCenter(cp)
            self.move(qr.topLeft())
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())