Kester
Kester

Reputation: 283

Qcombobox in PyQt, How could I set the options in one combo box which depends on the choice of other combo box?

For example, the first combo box with option A and option B. The second combo box contains option 1,2,3,4,5 if I select option A in 1st combo box. The second combo box contains option a,b,c,d,e if I select option B in 1st combo box.

How could I do this in PyQt5? I have searched Qcombobox class, there is 2 class activated and currentIndexChanged, but do not know which one I need to use and how to use it in PyQt5.

Upvotes: 3

Views: 9344

Answers (2)

FernAndr
FernAndr

Reputation: 1608

This is how I would do it:

import sys
from PyQt5 import QtWidgets


class ComboWidget(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super(ComboWidget, self).__init__(parent)
        self.setGeometry(50, 50, 200, 200)

        layout = QtWidgets.QVBoxLayout(self)

        self.comboA = QtWidgets.QComboBox()
        # The second addItem parameter is itemData, which we will retrieve later
        self.comboA.addItem('A', ['1', '2', '3', '4'])
        self.comboA.addItem('B', ['a', 'b', 'c', 'd', 'e'])
        self.comboA.currentIndexChanged.connect(self.indexChanged)
        layout.addWidget(self.comboA)

        self.comboB = QtWidgets.QComboBox()
        # We could have added the 1,2,3,4 items directly, but the following
        # is a bit more generic in case the combobox starts with a different
        # index for some reason:
        self.indexChanged(self.comboA.currentIndex())
        layout.addWidget(self.comboB)

        self.show()

    def indexChanged(self, index):
        self.comboB.clear()
        data = self.comboA.itemData(index)
        if data is not None:
            self.comboB.addItems(data)


def main():
    app = QtWidgets.QApplication(sys.argv)
    w = ComboWidget()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

That way, your code is a bit more future-proof, as it would allow you to add / modify / remove the items in any of the dropdowns quite easily if you wanted to do so at some point.

Upvotes: 3

Anonta
Anonta

Reputation: 2540

I got it working by using 3 comboboxes (lets call them x, y and z)

  1. x contains A, B and is used to choose what options appear on the other combobox. Selecting A shows combobox y and selecting B shows combobox z

  2. y contains 1,2,3,4

  3. Z contains a,b,c,d

I used a QStackedLayout in place of the second combobox, loaded it with two comboboxes (y and z) and showed one of them at a time depending on which option is selected in combobox x.

The method comboOptionChanged handles this. This method called whenever a different option in combobox x is chosen.

import sys
from PyQt5.QtWidgets import QWidget, QComboBox, QApplication, QFormLayout, QLabel,QStackedLayout

class DynamicComboExample(QWidget):
    def __init__(self):
        super().__init__()
        self.setupUI()

    def setupUI(self):
        self.setGeometry(300,300, 500, 300)
        self.show()

        combo_a = QComboBox(self)
        combo_a.addItem('A')
        combo_a.addItem('B')

        # set slot for when option of combobox A is changed
        combo_a.currentIndexChanged[int].connect(self.comboOptionChanged)

        self.combo_b = QComboBox()
        self.combo_b.addItem('1')
        self.combo_b.addItem('2')
        self.combo_b.addItem('3')
        self.combo_b.addItem('4')

        self.combo_c = QComboBox()
        self.combo_c.addItem('a')
        self.combo_c.addItem('b')
        self.combo_c.addItem('c')
        self.combo_c.addItem('d')
        self.combo_c.addItem('e')

        # use a stacked layout to view only one of two combo box at a time
        self.combo_container_layout = QStackedLayout()

        self.combo_container_layout.addWidget(self.combo_b)
        self.combo_container_layout.addWidget(self.combo_c)

        combo_container = QWidget()
        combo_container.setLayout(self.combo_container_layout)

        form_layout = QFormLayout()

        form_layout.addRow(QLabel('A:\t'), combo_a)

        # the stacked layout is placed in place of the (meant to be) second combobox
        form_layout.addRow(QLabel('B:\t'), combo_container)


        self.setLayout(form_layout)


    def comboOptionChanged(self, idx):
        ''' gets called when option for combobox A is changed'''

        # check which combobox_a option is selected ad show the appropriate combobox in stacked layout
        self.combo_container_layout.setCurrentIndex(0 if idx == 0 else 1)


def main():
    app= QApplication(sys.argv)
    w = DynamicComboExample()
    exit(app.exec_())

if __name__ == '__main__':
    main()

Upvotes: 0

Related Questions