绑定的c ++值未在QML

时间:2018-01-03 00:18:29

标签: c++ qt qml

我从.ini文件读取到c ++中的整数,然后通过绑定在QML中使用。在运行时,可以更改.ini文件中的值,这会导致c ++整数也被更改。我发现尽管整数确实在c ++中发生了变化(通过qDebug()验证),但QML中的绑定值并没有发生变化,尽管发出了所需的changed()信号。我的申请结构摘录如下:

main.cpp中:

//Establish the QQmlApplication engine, set context properties for the two c++ files and load the QML file.

QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("MainCpp"), new MainCpp());
engine.rootContext()->setContextProperty(QStringLiteral("Config"), new Config());
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

maincpp.h:

public:
    explicit MainCpp(QObject *parent = nullptr);

    Q_PROPERTY(int someValue READ someValue NOTIFY someValueChanged)
    int someValue(){return m_someValue;}

signals:
    void someValueChanged();

private:
    int    m_someValue;

的config.h:

public:
    explicit Config(QObject *parent = nullptr);

    Q_PROPERTY(int someOtherValue READ someOtherValue NOTIFY someOtheralueChanged)
    int someOtherValue(){return m_someOtherValue;}

signals:
    void someOtherValueChanged();

public:
    void loadSettings();

public:
    int      m_someOtherValue;
    QString  m_File;

config.cpp:

Config::Config(QObject *parent) : QObject(parent)
{
    m_File = "/some/path/to/settings/file/config.ini";
    loadSettings();
}

void Config::loadSettings()
{
    QSettings settings(m_File, QSettings::IniFormat);
    settings.beginGroup("GROUP_NAME");
    m_someOtherValue = settings.value("someOtherValueConfig", "").toInt();
    settings.endGroup();
}

maincpp.cpp:

MainCpp::MainCpp(QObject *parent = nullptr) : QObject(parent)
{
    Config configPointer;
    m_someValue = configPointer.someOtherValue();
    emit someValueChanged();
}

main.qml:

Window {
    width: 800
    height: 480

    Text {
        id: someText
        text: Config.someOtherValue //This does NOT update on changes to m_someOtherValue on the c++ side
        //text: MainCpp.someValue //This DOES update on change to m_someValue on the c++ side
    }
}

在maincpp.cpp中调用以下代码来更新.ini文件:

void MainCpp::update(int var)
{
    Config configPointer;

    QSettings settings("/some/path/to/settings/file/config.ini", QSettings::IniFormat);
    settings.setValue("GROUP_NAME/someOtherValueConfig", var);
    configPointer.m_someOtherValue = var;
    m_someValue = configPointer.someOtherValue;
    emit configPointer.someOtherValueChanged();
    emit someValueChanged();
}

我已经添加了#OtherValueChanged()'信号无济于事。如前所述,我知道m_someOtherValue已经改变,因为我使用qDebug()查询它。如果m_someValue发生变化,为什么QML没有观察到m_someOtherValue的变化?

1 个答案:

答案 0 :(得分:1)

导致该行为是因为您有3个Config对象:

  1. 的main.cpp
  2. engine.rootContext()->setContextProperty(QStringLiteral("Config"), new Config());
    
    1. MainCpp构造函数:
    2. MainCpp::MainCpp(QObject *parent = nullptr) : QObject(parent)
      {
          Config configPointer; 
          [...]
      
      1. 更新方法:
      2. void MainCpp::update(int var)
        {
            Config configPointer;
        

        也就是说,如果其中一些更改不会更改其他对象,因为它们不同。

        一种可能的解决方案是使Config成为Singleton,因此整个应用程序中的所有对象都是相同的。

        <强>的config.h

        #ifndef CONFIG_H
        #define CONFIG_H
        
        #include <QObject>
        #include <QSettings>
        
        class Config : public QObject
        {
            static Config* instance;
            Q_OBJECT
            Q_PROPERTY(int someOtherValue READ someOtherValue NOTIFY someOtherValueChanged)
            explicit Config(QObject *parent = nullptr);
        
        public:
            static Config *getInstance();
            int someOtherValue(){return m_someOtherValue;}
            [...]
        
        };
        
        #endif // CONFIG_H
        

        <强> config.cpp

        #include "config.h"
        
        Config* Config::instance = 0;
        
        Config::Config(QObject *parent):QObject(parent){
            m_File = "/some/path/to/settings/file/config.ini";
            loadSettings();
        }
        
        Config *Config::getInstance(){
            if (instance == 0)
                instance = new Config;
            return instance;
        }
        
        void Config::loadSettings(){
            [...]
        }
        

        然后通过getInstance()访问该对象:

        <强> maincpp.cpp

        #include "maincpp.h"
        
        MainCpp::MainCpp(QObject *parent):QObject(parent){
            Config *configPointer = Config::getInstance();
            m_someValue = configPointer->someOtherValue();
            emit someValueChanged();
        }
        
        void MainCpp::update(int var)
        {
            Config *configPointer = Config::getInstance();
            QSettings settings("/some/path/to/settings/file/config.ini", QSettings::IniFormat);
            settings.setValue("GROUP_NAME/someOtherValueConfig", var);
            configPointer->m_someOtherValue = var;
            m_someValue = configPointer->someOtherValue();
            emit configPointer->someOtherValueChanged();
            emit someValueChanged();
        }
        

        要在QML中使用它,您必须在qmlRegisterSingletonType()

        的帮助下注册

        <强>的main.cpp

        #include "maincpp.h"
        
        #include <QGuiApplication>
        #include <QQmlApplicationEngine>
        #include <QQmlContext>
        
        static QObject *singletonTypeProvider(QQmlEngine *, QJSEngine *)
        {
            return Config::getInstance();
        }
        
        int main(int argc, char *argv[])
        {
        #if defined(Q_OS_WIN)
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        #endif
        
            QGuiApplication app(argc, argv);
            qmlRegisterSingletonType<Config>("Config", 1, 0, "Config", singletonTypeProvider);
        
            QQmlApplicationEngine engine;
            engine.rootContext()->setContextProperty(QStringLiteral("MainCpp"), new MainCpp());
            engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
            if (engine.rootObjects().isEmpty())
                return -1;
        
            return app.exec();
        }
        

        在qml中,您必须导入模块并使用对象:

        import QtQuick 2.9
        import QtQuick.Window 2.2
        import QtQuick.Controls 1.4
        import QtQuick.Layouts 1.3
        
        import Config 1.0
        
        Window {
            width: 800
            height: 480
            visible: true
        
            ColumnLayout{
        
                Text {
                    id: someText
                    text: Config.someOtherValue
                }
                Text {
                    id: anotherText
                    text: MainCpp.someValue
                }
        
                Slider {
                    value: 0.5
                    maximumValue: 100
                    onValueChanged: MainCpp.update(value)
                }
            }
        }
        

        完整示例可在以下link中找到。