Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Q_属性变量的动态赋值_C++_Qt_Qml - Fatal编程技术网

C++ Q_属性变量的动态赋值

C++ Q_属性变量的动态赋值,c++,qt,qml,C++,Qt,Qml,情况就是这样 QQmlApplicationEngine* engine; QQmlContext* ctxt; class Fruit: public QObject { Q_OBJECT Q_PROPERTY(QString type MEMBER m_type NOTIFY fruitChanged) private: QString m_type; public: virtual void initFruit() = 0; void star

情况就是这样

QQmlApplicationEngine* engine;
QQmlContext* ctxt;

class Fruit: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString type MEMBER m_type NOTIFY fruitChanged)

private:
    QString m_type;
public:
    virtual void initFruit() = 0;

    void startEating(){
        initFruit();
        ctxt->setContextProperty("fruit", this);
        engine->load(QUrl(QLatin1String("qrc:/qml/main.qml"))); 

       app.exec();
       engine->quit();
       engine->deleteLater();
    }

    void setType(QString fruit){
        m_type = fruit;
        emit fruitChanged();
    }
signals:
    fruitChanged();
};

class Apple:public Fruit{
public:
    explicit Appl(QObject *parent = nullptr);

    void initFruit(){
        Slice slice = new Slice();    // some other class
        ctxt->setContextProperty("slice", slice);
    }
};

class Banana:public Fruit{
public:
    explicit Banana(QObject *parent = nullptr);

    void initFruit(){
        Peel peel = new Peel();      // some other class
        ctxt->setContextProperty("peel", peel);
    }
};

class Peel: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString color MEMBER m_peelColor NOTIFY peelChanged)

private:
    QString m_peelColor;
signals:
    void peelChanged();
public:
    void someFunction(QString peelColor){
        m_peelColor = peelColor;
        emit peelChanged();
    }
}

class Slice: public QObject
{
    Q_OBJECT
    Q_PROPERTY(int number MEMBER m_slices NOTIFY sliceChanged)

private:
    QString m_slices;
signals:
    void sliceChanged();
public:
    void someFunction(QString slices){
        m_slices = slices;
        emit sliceChanged();
    }
}

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

    Fruit *fruit;

    if (argv[1] == "Apple"){
        fruit = new Apple();
    }
    else if (argv[1] == "Banana"){
        fruit = new Banana();
    }

    engine = new QQmlApplicationEngine();
    ctxt = engine->rootContext();

    fruit->setType(argv[1].toString());
    fruit->startEating();
}
然后在main.qml中

...
Rectangle{
     Text {
        text: {    // I want to remove this if else statement
            if(fruit.type == "Apple")
                slice.number
            else if(fruit.type == "Banana") 
                peel.color
        }
    }
}

您可以想象,随着水果数量的增加,main.qml中的if-else语句会变得多大。因此,我想知道是否有一种不同的方法来处理这样的场景,在这种情况下,我可以以某种方式将qml中的文本指定为一个值,然后它动态加载正确的后端属性

与其在initFruit方法中注册新的数据类型并使用全局变量,不如创建一个提供程序类:

#包括
#包括
#包括
#包括
类别:公共QObject
{
Q_对象
公众:
虚拟Q_可调用的QString name()=0;
};
苹果类:公众水果{
公众:
QString名称(){
返回“苹果”;
}
};
香蕉类:公共水果{
公众:
QString名称(){
返回“香蕉”;
}
};
类提供者:公共QObject{
Q_对象
Q_属性(水果*水果读取水果写入设置水果通知水果更改)
公众:
水果提供者(QObject*parent=nullptr):QObject(parent){}
水果常数{
返回m_水果。获取();
}
公众时段:
空果(果*果){
m_水果。重置(水果);
发出改变的声音();
}
Q_信号:
无效,无效();
私人:
qscopedpointermu水果;
};
int main(int argc,char*argv[]){
QCoreApplication::setAttribute(Qt::AA_enableHighdDiscaling);
QGUI应用程序应用程序(argc、argv);
水果供应商;
如果(argc<1){
返回-1;
}
如果(std::strcmp(argv[1],“Apple”)==0){
provider.setFruit(新苹果());
}
else if(std::strcmp(argv[1],“Banana”)==0){
provider.setFruit(新香蕉());
}
qqmlaplicationengine;
engine.rootContext()->setContextProperty(“提供者”、&provider);
const-QUrl-url(QStringLiteral(“qrc:/main.qml”);
QObject::connect(&engine),&QQmlApplicationEngine::objectCreated,
&应用程序,[url](QObject*obj,const-quorl和objUrl){
如果(!obj&&url==objUrl)
QCoreApplication::退出(-1);
},Qt::QueuedConnection);
引擎加载(url);
返回app.exec();
}
#包括“main.moc”
更新:

正如我在评论中指出的,消除if-elseif-else的想法是为了标准化对属性的访问,对于水果,您可以使用提供者。对于“数字”和“颜色”属性,您可以创建一个通用属性,该属性在每次修改其他属性时都会更新,并使用该属性访问QML中的信息

#包括
#包括
#包括
#包括
类:公共QObject{
Q_对象
Q_属性(QString颜色成员m_peelColor NOTIFY peelChanged)
私人:
QString m_peelColor;
信号:
void peelChanged();
公众:
void someFunction(QString peelColor){
m_peelColor=peelColor;
发射peelChanged();
}
};
类切片:公共QObject{
Q_对象
Q_属性(整数成员m_已更改)
私人:
int m_切片;
信号:
void sliceChanged();
公众:
void函数(int切片){
m_切片=切片;
发射切片改变();
}
};
类别:公共QObject{
Q_对象
Q_属性(QVariant公共成员m_公共通知公共更改)
公众:
无效开始测试(){
initFruit();
}
QVariant common()常量{
返回m_common;
}
Q_信号:
void commonChanged();
受保护的:
虚拟void initFruit()=0;
void setCommon(QVariant common){
m_公共=公共;
emit commonChanged();
}
私人:
qm_公共变量;
};
苹果类:公众水果{
公众:
虚无的果实(){
重置(新切片());
切片->函数(100);
setCommon(切片->属性(“编号”);
连接(slice.get(),&slice::sliceChanged,[this](){
setCommon(切片->属性(“编号”);
});
}
私人:
QScopedPointer切片;
};
香蕉类:公共水果{
公众:
虚无的果实(){
剥离。重置(新剥离());
剥离->某些功能(“红色”);
setCommon(剥离->属性(“颜色”);
连接(peel.get(),&peel::peelChanged,[this](){
setCommon(剥离->属性(“颜色”);
});
}
私人:
QScopedPointer果皮;
};
类提供者:公共QObject{
Q_对象
Q_属性(水果*水果读取水果写入设置水果通知水果更改)
公众:
水果常数{
返回m_水果。获取();
}
公众时段:
空果(果*果){
m_水果。重置(水果);
发出改变的声音();
}
Q_信号:
无效,无效();
私人:
qscopedpointermu水果;
};
int main(int argc,char*argv[]){
QCoreApplication::setAttribute(Qt::AA_enableHighdDiscaling);
QGUI应用程序应用程序(argc、argv);
水果供应商;
如果(argc<1){
返回-1;
}
如果(std::strcmp(argv[1],“Apple”)==0){
provider.setFruit(新苹果());
}
else if(std::strcmp(argv[1],“Banana”)==0){
provider.setFruit(新香蕉());
}
qqmlaplicationengine;
engine.rootContext()->setContextProperty(“提供者”、&provider);
const-QUrl-url(QStringLiteral(“qrc:/main.qml”);
QObject::connect(&engine),&QQmlApplicationEngine::objectCreated,
&应用程序,[url](QObject*obj,const-quorl和objUrl){
如果(!obj&&url==objUrl)
QCoreApplication::退出(-1);
},Qt::QueuedConnection);
引擎加载(url);
provider.fruit()->startEating();
返回app.exec();
}
#包括“main.moc”

打字错误:更改<代码>更改到<代码>已更改()Text{ text: provider.fruit.name() }
Text{
    text: provider.fruit.common
}