Omega
Omega

Reputation: 19

How to connect checkboxes to a QComboBox

I would like to filter the items in a PyQt5 QCombobox when checking certain checkboxes.

Example:

samplelist=["a1","a2","a3","b1","b2","b3"] is the list of items of the QCombobox comboBox and I have two checkboxes checkBoxa and checkBoxb. If

Does anyone have an idea how I can connect checkboxa and checkbox to the comboBox to achieve the described result?

Minimal example (checkboxes are not connected to the combobox)

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *  

class ExampleWindow(QDialog):
    def __init__(self,parent=None):
        super(ExampleWindow,self).__init__(parent)

        mainLayout=QtWidgets.QGridLayout()
        
        samplelist=["a1","a2","a3","b1","b2","b3"]

        # Create combobox and add items.
        self.comboBox = QComboBox()
        self.comboBox.addItems(samplelist)

        #Create checkboxes
        self.checkBoxa = QCheckBox("Select a") 
        self.checkBoxb = QCheckBox("Select b")
        
        mainLayout.addWidget(self.comboBox,1,0,1,2)
        mainLayout.addWidget(self.checkBoxa,0,0,1,1)
        mainLayout.addWidget(self.checkBoxb,0,1,1,1)
        

        self.setLayout(mainLayout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = ExampleWindow()
    mainWin.show()
    sys.exit( app.exec_() )

Upvotes: 1

Views: 212

Answers (1)

eyllanesc
eyllanesc

Reputation: 243907

Since your question is not explicit, I will assume that each QCheckBox is associated with a letter and you want to show only the items that start with a letter associated with the checked QCheckBoxs. If so then it is better to create a model based on the items and filter them using a QSortFilterProxyModel.

class FilterProxyModel(QSortFilterProxyModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._letters = list()

    @property
    def letters(self):
        return self._letters

    @letters.setter
    def letters(self, letters):
        self._letters = letters.copy()
        self.invalidateFilter()

    def filterAcceptsRow(self, source_row, source_parent):
        index = self.sourceModel().index(source_row, 0, source_parent)
        data = index.data()
        return any(data.startswith(letter) for letter in self.letters)


class ExampleWindow(QDialog):
    def __init__(self, parent=None):
        super(ExampleWindow, self).__init__(parent)

        mainLayout = QGridLayout(self)

        letters = ("a", "b", "c", "d")

        samplelist = [f"{letter}{i}" for i in range(1, 5) for letter in letters]

        self.model = QStandardItemModel()
        for e in samplelist:
            item = QStandardItem(e)
            self.model.appendRow(item)

        self.proxy_model = FilterProxyModel()
        self.proxy_model.setSourceModel(self.model)

        self.comboBox = QComboBox()
        self.comboBox.setModel(self.proxy_model)

        self.checkboxs = []

        for i, letter in enumerate(letters):
            checkbox = QCheckBox(f"Select {letter}")
            checkbox.setProperty("letter", letter)
            checkbox.toggled.connect(self.handle_toggled)
            mainLayout.addWidget(checkbox, 0, i)
            self.checkboxs.append(checkbox)

        mainLayout.addWidget(self.comboBox, 1, 0, 1, len(letters))

        self.handle_toggled()

    def handle_toggled(self):
        letters = []
        for checkbox in self.checkboxs:
            if checkbox.isChecked():
                letters.append(checkbox.property("letter"))
        self.proxy_model.letters = letters

Upvotes: 1

Related Questions