QML动态ComboBox条目

时间:2014-11-12 12:46:19

标签: c++ qt combobox model qml

我试图在QML和C ++中实现一个ComboBox,我可以动态地改变我的ComboBox的内容。我提供了一个QStringList作为ComboBox-Model,并希望使用两个按钮从ComboBox插入/删除一个条目。

我可以在我的ComboBox中显示QStringList,但是当我点击Add-Button时,我的QStringList会在我的类中更新,但不知何故View不会更新ComboBox。我应该怎么做,告诉View我的ComboBox-Model已更新?

这是我的代码:

comboboxmodel.h

#ifndef COMBOBOXMODEL_H
#define COMBOBOXMODEL_H

#include <QObject>
#include <QStringList>

class ComboBoxModel : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QStringList comboList READ comboList WRITE setComboList NOTIFY comboListChanged)
    Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)

public:
    ComboBoxModel(QObject *parent = 0);
    ComboBoxModel(const QStringList &list,int count, QObject *parent = 0);

    const QStringList comboList();
    void setComboList(const QStringList &comboList);

    int count();
    void setCount(int cnt);

    Q_INVOKABLE void addElement(const QString &element);
    Q_INVOKABLE void removeElement(int index);

signals:

    void comboListChanged();
    void countChanged();

public slots:


private:

    QStringList m_comboList;
    int         m_count;
};

#endif // COMBOBOXMODEL_H

comboboxmodel.cpp

#include "comboboxmodel.h"
#include "qdebug.h"

ComboBoxModel::ComboBoxModel(QObject *parent) :
    QObject(parent)
{
}

ComboBoxModel::ComboBoxModel(const QStringList &list, int count, QObject *parent) :
    QObject(parent), m_comboList(list), m_count(count)
{

}

const QStringList ComboBoxModel::comboList()
{
    return m_comboList;
}

void ComboBoxModel::setComboList(const QStringList &comboList)
{

    if (m_comboList != comboList)
    {
        m_comboList = comboList;
        emit comboListChanged();
    }

}

int ComboBoxModel::count()
{
    return m_count;
}

void ComboBoxModel::setCount(int cnt)
{
    if (cnt != m_count)
    {
        m_count = cnt;
        emit countChanged();
    }
}

void ComboBoxModel::addElement(const QString &element)
{
    m_comboList.append(element);
    emit comboListChanged();
    setCount(m_comboList.count());
    emit countChanged();

    for (int i = 0; i<m_count; i++)
    {
        qDebug() << m_comboList.at(i);
    }
}

void ComboBoxModel::removeElement(int index)
{
    if (index < m_comboList.count())
    {
        m_comboList.removeAt(index);
        emit comboListChanged();
        setCount(m_comboList.count());
        emit countChanged();
    }

    for (int i = 0; i<m_count; i++)
    {
        qDebug() << m_comboList.at(i);
    }
}

的main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <qqmlengine.h>
#include <qqmlcontext.h>
#include <qqml.h>
#include <QStringList>

#include "comboboxmodel.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);


    QQmlApplicationEngine engine;
    ComboBoxModel combo;

    QStringList tmp;
    tmp << "1" << "2" << "3" << "4" << "5" << "6" << "7";
    combo.setComboList(tmp);

    QQmlContext *ownContext = engine.rootContext();
    ownContext->setContextProperty("myModel", QVariant::fromValue(combo.comboList()));

    QQmlContext *classContext = engine.rootContext();
    classContext->setContextProperty("comboModel", &combo);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec(); }

main.qml

import QtQuick 2.3 import QtQuick.Controls 1.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: console.log("Open action triggered");
            }
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }

    ComboBox {
        id: comboBox1
        x: 258
        y: 54
        model: myModel
        editable: true
        onAccepted: {
             if (editableCombo.find(currentText) === -1) {
                 model.append({text: editText})
                 currentIndex = editableCombo.find(editText)
             }
         }

    }

    Button {
        id: button1
        x: 280
        y: 139
        text: qsTr("Remove Item")
        onClicked: comboModel.removeElement(comboBox1.currentIndex)
    }

    Rectangle{
        x: 281
        y: 316
        width: 80
        height: 20
        color: "white"

        TextEdit {
            id: textEdit1
            width: 80
            height: 20
            text: qsTr("Text Edit")
            font.pixelSize: 12
        }
    }

    Button {
        id: button2
        x: 280
        y: 388
        text: qsTr("Add Item")
        onClicked: comboModel.addElement(textEdit1.text)
    } }

2 个答案:

答案 0 :(得分:3)

所以我最终想出了如何做这种事情。

在main.qml中应该是:

model: comboModel.comboList

而不是:

model: myModel

现在,我可以添加/删除列表中的项目,并正确显示。

感谢您提示BaCaRoZzo。

有人可以将此主题更改为&#34;已解决&#34;?

答案 1 :(得分:1)

这个例子对我有很大帮助,谢谢!这是一个稍作修改的版本,作为完成的工作示例:

comboboxmodel.h

#ifndef COMBOBOXMODEL_H
#define COMBOBOXMODEL_H

#include <QObject>
#include <QStringList>

class ComboBoxModel : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QStringList comboList READ comboList WRITE setComboList NOTIFY comboListChanged)
    Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)
    Q_PROPERTY(int currentIndex READ currentIndex WRITE setcurrentIndex NOTIFY currentIndexChanged)

public:
    ComboBoxModel(QObject *parent = 0);
    ComboBoxModel(const QStringList &list,int count, QObject *parent = 0);

    const QStringList comboList();
    void setComboList(const QStringList &comboList);

    int count();
    void setCount(int cnt);

    int currentIndex();
    void setcurrentIndex(int index);

    Q_INVOKABLE void addElement(const QString &element);
    Q_INVOKABLE void removeElement(int index);

signals:

    void comboListChanged();
    void countChanged();
    void currentIndexChanged();

public slots:


private:

    QStringList m_comboList;
    int         m_count;
    int         m_currentIndex;
};

#endif // COMBOBOXMODEL_H

comboboxmodel.cpp

#include "comboboxmodel.h"
#include "qdebug.h"

ComboBoxModel::ComboBoxModel(QObject *parent) :
    QObject(parent)
{
}

ComboBoxModel::ComboBoxModel(const QStringList &list, int count, QObject *parent) :
    QObject(parent), m_comboList(list), m_count(count)
{

}

const QStringList ComboBoxModel::comboList()
{
    return m_comboList;
}

void ComboBoxModel::setComboList(const QStringList &comboList)
{

    if (m_comboList != comboList)
    {
        m_comboList = comboList;
        emit comboListChanged();
    }

}

int ComboBoxModel::count()
{
    return m_count;
}

void ComboBoxModel::setCount(int cnt)
{
    if (cnt != m_count)
    {
        m_count = cnt;
        emit countChanged();
    }
}

int ComboBoxModel::currentIndex()
{
    return m_currentIndex;
}

void ComboBoxModel::setcurrentIndex(int index)
{
    if (index != m_currentIndex)
    {
        m_currentIndex = index;
        qDebug()<<"current index is"<<index;
        emit currentIndexChanged();
    }
}
void ComboBoxModel::addElement(const QString &element)
{
    m_comboList.append(element);
    emit comboListChanged();
    setCount(m_comboList.count());
    emit countChanged();

    for (int i = 0; i<m_count; i++)
    {
        qDebug() << m_comboList.at(i);
    }
}

void ComboBoxModel::removeElement(int index)
{
    if (index < m_comboList.count())
    {
        m_comboList.removeAt(index);
        emit comboListChanged();
        setCount(m_comboList.count());
        emit countChanged();
    }

    for (int i = 0; i<m_count; i++)
    {
        qDebug() << m_comboList.at(i);
    }
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <QStringList>

#include "comboboxmodel.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    ComboBoxModel combo;

    QStringList tmp;
    tmp << "1" << "2" << "3" << "4" << "5" << "6" << "7";
    combo.setComboList(tmp);

    QQmlContext *ownContext = engine.rootContext();
    ownContext->setContextProperty("myModel", QVariant::fromValue(combo.comboList()));

    QQmlContext *classContext = engine.rootContext();
    classContext->setContextProperty("comboModel", &combo);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

main.qml

import QtQuick 2.3
import QtQuick.Controls 2.2

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }

    ComboBox {
        id: comboBox1

        x: 258
        y: 54
        model: comboModel.comboList
        onActivated: {
            console.log("combomodel activated" + comboBox1.currentIndex)
            comboModel.currentIndex = comboBox1.currentIndex
         }

    }

    Button {
        id: button1
        x: 280
        y: 139
        text: qsTr("Remove Item")
        onClicked: comboModel.removeElement(comboBox1.currentIndex)
    }

    Rectangle{
        x: 281
        y: 316
        width: 80
        height: 20
        color: "white"

        TextEdit {
            id: textEdit1
            width: 80
            height: 20
            text: qsTr("Text Edit")
            font.pixelSize: 12
        }
    }

    Button {
        id: button2
        x: 280
        y: 388
        text: qsTr("Add Item")
        onClicked: comboModel.addElement(textEdit1.text)
    } }

原始文件

QT += quick
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += main.cpp \
    comboboxmodel.cpp

RESOURCES += qml.qrc

QML_IMPORT_PATH =
QML_DESIGNER_IMPORT_PATH =

qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    comboboxmodel.h