Python Forum

Full Version: PyQt4 dynamic QComboBox
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I need to dynamically add combos to a parent form. Selecting a value in the combo should call a method in the parent form to dynamically update the screen.

I've created a custom ComboBox class that inherits from QWidget:

from PyQt4 import QtCore, QtGui


class PartRoleComboBox(QtGui.QWidget):

    def __init__(self, form, object_name):
        QtGui.QWidget.__init__(self)
        self.parent_form = form
        self.dd = QtGui.QComboBox()
        self.available_options = ['Hardware', 'Base', 'Case', 'Drawer']
        self.dd.addItems(self.available_options)
        self.dd.currentIndexChanged.connect(self.part_role_selection_changed)
        self.dd.setObjectName(object_name)
        # dd.setToolTip("Choose a part role to configure", None)
        self.dd.sizeHint()

    def part_role_selection_changed(self):
        print("dropdown selection changed")
        self.parent_form.add_part_role_shadows_table(self.currentText())
And in the parent form, I have a method to add the dropdown:

    def add_part_role_dropdown(self):
        # Add a dropdown control containing list of part roles
        obj_name = "ddnSection" + str(self.section)
        dd = prCombo(self.form, obj_name)
        self.gridLayout.addWidget(dd, self.section+4, 1, 1, 1, QtCore.Qt.AlignHCenter)
I'm not getting an error message, or any feedback. It steps through the code cleanly, but the combo is never shown to the user.

Any ideas?
The combo is not shown because it (self.dd) is not added to the layout. You should subclass QComboBox directly instead of QWidget, unless you really need QWidget methods.

#!/usr/bin/python3
import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Main(QtWidgets.QMainWindow):
    def __init__(self, parent):
        super().__init__()
        self.ui = QtWidgets.QWidget(self)
        self.setCentralWidget(self.ui)
        self.ui.combo = PartRoleComboBox()
        self.ui.layout = QtWidgets.QVBoxLayout()
        self.ui.layout.addWidget(self.ui.combo)
        self.ui.setLayout(self.ui.layout)
        self.show()

        def add_part_role_dropdown(self):
            # Add a dropdown control containing list of part roles
            obj_name = "ddnSection" + str(self.section)
            dd = prCombo(self.form, obj_name)
            self.gridLayout.addWidget(dd, self.section+4, 1, 1, 1, QtCore.Qt.AlignHCenter)

class PartRoleComboBox(QtWidgets.QComboBox):

    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        #self.parent_form = form
        self.available_options = ['Hardware', 'Base', 'Case', 'Drawer']
        self.addItems(self.available_options)
        self.currentIndexChanged.connect(self.part_role_selection_changed)
        ##self.setObjectName(object_name)
        # dd.setToolTip("Choose a part role to configure", None)
        self.sizeHint()

    def part_role_selection_changed(self):
        print("dropdown selection changed")
        print(self.currentText())
        #self.parent_form.add_part_role_shadows_table(self.currentText())


if __name__== '__main__':
    app = QtWidgets.QApplication([])
    gui = Main(app)
    sys.exit(app.exec_())
Thank you for the feedback. You have gotten me a step closer. However, my project has PyQt4 and Python 2.7 constraints. The dropdown is now showing, but the selection changed event is never fired.
To use the example in PyQt4, you can change calls to QtWidgets with QtGui. The change signal works for that code, perhaps we can help you more if you share your complete (relevant) code.
Thank you. I was able to get it working. Not sure if it is the best solution, but I moved the selection changed event from the custom combo-box class to the UI class and now it seems to consistently fire.

    def add_part_role_dropdown(self):
        # Add a dropdown control containing list of part roles
        obj_name = "ddnSection" + str(self.section)
        dd = prCombo(self.form, obj_name)
        dd.dd.activated[str].connect(self.part_role_selection_changed)
        self.gridLayout.addWidget(dd.dd, self.section+4, 1, 1, 1, QtCore.Qt.AlignHCenter)

    def part_role_selection_changed(self, selected_text):
        print("dropdown selection changed")
        self.add_part_role_shadows_table(selected_text)