Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Example of a model for use with QtQuick ComboBox (qml)



  • Does anyone have an example of a pyside2 model for use with a QComboBox? It seems that no matter what I throw at it, it either doesn't render the text properly, or doesn't accept the model.

    I've attempted modified models with both QStandardItemModel and QAbstractItemModel. I only need to load the ComboBox with a list of strings.

    Is there documentation or a way that I reveals the default model?



  • Solved this... turns out I was trying to hard...

    A python list will automatically be converted to a QStringList for qml. To update the model, just call engine.rootContext().setContextProperty() again as the combobox doesn't know when the string list changes.

    .py code

    comportComboModel = ['1','2','3','4','5']
    engine.rootContext().setContextProperty("comModel", comportComboModel)
    

    .qml code

    ComboBox {
                    id: comComboBox
                    width: 100
                    font.pointSize: 12
                    rightPadding: 0
                    currentIndex: 0
                    flat: true
                    model: comModel
                }
    

    image


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Since it's just a list of strings, why not use QComboBox.addItems ?



  • @SGaist Honestly, I'm not 100% how to. I can modify buttons and text just fine, but every time I try to clear/addItems/etc to this ComboBox it ignores it. Signal/Slots between qml and python is very convoluted at times. The combobox needs to be continuously updated, so it would be cleaner and easier to manage with model. I think addItems() and clear() aren't working because i'm initializing the model in qml?

    I'm trying to figure out how to format QStandardItemModel properly so it accepts it.

    Here is some example test code. The function prints the log entry 'adding 4!' but does not add the item to the list. I've tried other commands and also "Connections" with the signal, etc. I can't seem to edit the ComboBox model in anyway.

    .py
    
    class Backend(QObject):
    
        addToModel = Signal()
    
        def __init__(self):
            QObject.__init__(self)
            QTimer.singleShot(1000, self.add)
    
        def add(self):
            self.addToModel.emit()
    
    ...
    
        app = QGuiApplication(sys.argv)
        engine = QQmlApplicationEngine()
        backend = Backend()
    
        # link engine to logic, load single qml file
        engine.rootContext().setContextProperty("backend", backend)
        engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
    
    ...
    
    
    .qml
    
    ComboBox {
                    id: comportComboBox
                    width: 100
                    font.pointSize: 12
                    rightPadding: 0
                    currentIndex: 0
                    flat: true
                    model: ['1','2','3']
    
                    Component.onCompleted: backend.addToModel.connect(addToModel)
    
                    function addToModel() {
                        backend.log('adding 4!')
                        comportComboBox.additems(["4"])
                    }
    
                }
    


  • Update to the situation, QComboBox is accepting a QStandardItemModel now, but doesn't display text (it only displays 10 empty boxes). It the default model storing draw data somehow?

    .py code

    class ComboBoxModel(QStandardItemModel):
    
        def __init__(self):
            QStandardItemModel.__init__(self)
            for x in range(10):
                item = QStandardItem(str(x))
                item.setCheckable(True)
                self.appendRow(item)
    
    self.comComboModel = ComboBoxModel()
    
    engine.rootContext().setContextProperty("comComboModel", leash.comportComboModel)
    

    .qml code

                ComboBox {
                    id: comComboBox
                    width: 100
                    font.pointSize: 12
                    rightPadding: 0
                    currentIndex: 0
                    flat: true
                    model: comportComboModel
                }
    

    The problem is it displays this...

    image


  • Lifetime Qt Champion

    Sorry I missed the part about QML. QComboBox is part of the Qt widgets module and it's not the same a a QtQuick ComboBox.

    As for using custom models, did you already took a look at the C++ version of the QtQuick Model Views Data chapter of Qt's documentation ? That should give you the basic knowledge to create custom models. You'll have to translate that to Python though.



  • @SGaist thanks, I don't really follow that documentation. I tried to create a QStringListModel in python and passed it to QtQuick ComboBox. It does the same thing as before, it renders the combobox list and has the correct number of items (I can hover and see them light up) but the text still doesn't display. I assume QtQuick ComboBox either isn't converting the strings properly, or I'm not storing the strings properly?

    .py code

    class ComboBoxModel2(QStringListModel):
    
        def __init__(self):
            QStringListModel.__init__(self)
            self.setStringList(['1','2','3','4'])
    
    self.comComboModel2 = ComboBoxModel2()
    
    engine.rootContext().setContextProperty("comComboModel2", leash.comportComboModel2)
    

    .qml code

    ComboBox {
                    id: comComboBox
                    width: 100
                    font.pointSize: 12
                    rightPadding: 0
                    currentIndex: 0
                    flat: true
                    model: comComboModel2
                }
    

    Once again this displays the 4 buttons, but they do not contain text. Frustrating to say the least... python and qml do not play nice.

    image



  • Solved this... turns out I was trying to hard...

    A python list will automatically be converted to a QStringList for qml. To update the model, just call engine.rootContext().setContextProperty() again as the combobox doesn't know when the string list changes.

    .py code

    comportComboModel = ['1','2','3','4','5']
    engine.rootContext().setContextProperty("comModel", comportComboModel)
    

    .qml code

    ComboBox {
                    id: comComboBox
                    width: 100
                    font.pointSize: 12
                    rightPadding: 0
                    currentIndex: 0
                    flat: true
                    model: comModel
                }
    

    image


Log in to reply