【问题标题】:Why can I not assign this Qt property?为什么我不能分配这个 Qt 属性?
【发布时间】:2018-05-27 23:06:56
【问题描述】:

Qt 在运行时抛出以下错误。

Unable to assign LIMITS_T to LIMITS_T

我假设 Qt 需要更多元数据信息,但我不知道我错过了什么。我已经做了一切来声明元类型:

limits.h

class LIMITS_T : public QObject{
    Q_OBJECT
    Q_PROPERTY(float min READ readMin WRITE writeMin NOTIFY minChanged)

public:
    LIMITS_T() : QObject() {}
    LIMITS_T(const LIMITS_T& limit) : QObject()
    {
        this->min = limit.min;
    }

    float min = 0;

    float readMin() { return min; }
    void writeMin(float min) { this->min = min; }

    bool operator = (const LIMITS_T &limit)
    {
        this->min = limit.min;
    }

signals:
    void minChanged();
};

Q_DECLARE_METATYPE(LIMITS_T)

这是 splitBarGauge 类的简化版本

splitDialGauge.h

class SplitDialGauge : public QQuickPaintedItem
{
    Q_OBJECT
    Q_PROPERTY(LIMITS_T limits READ getLimits WRITE setLimits NOTIFY limitsChanged)

public:
    SplitDialGauge(QQuickItem *parent = 0);

protected:
    LIMITS_T limits;
    virtual LIMITS_T getLimits();
    virtual void setLimits(LIMITS_T value);
}

splitDialGauge.cpp

#include "splitBarGauge.h"

SplitDialGauge::SplitDialGauge(QQuickItem *parent = 0);
    : QQuickPaintedItem(parent)
{
}

LIMITS_T SplitDialGauge::getLimits()
{
    return this->limits;
}

void SplitDialGauge::setLimits(LIMITS_T limits)
{
    this->limits = limits;
    update();
}

我在 Qt 元数据系统中注册了该类

#include "limits.h"
#include "splitDialGauge.h"
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    qmlRegisterType<SplitDialGauge>("ExampleModule", 1, 0, "SplitDialGauge");
    qmlRegisterType<LIMITS_T>("ExampleModule", 1, 0, "Limits");
    qRegisterMetaType<LIMITS_T>();

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

    return app.exec();
}

这是来自 QML 文件的片段

import ExampleModule 1.0

ApplicationWindow {
    visible: true
    width: 800
    height: 480

    SplitDialGauge {
        Limits {
            id: qtyLimits
            min: 4
        }
        height: 200
        width: 50
        limits: qtyLimits
    }
}

【问题讨论】:

  • 这是 Qt,不是 QT。 QT 代表快速时间。
  • @InnokentiyAlaytsev 对不起。修复了
  • 我已经尝试了 LIMITS_T,但它并没有抛出那个错误,我不能将它与 SplitBarGauge 一起使用,因为它似乎不是 Qt 的一部分。
  • @InnokentiyAlaytsev 现在你是 qute。
  • 我看到你在覆盖操作符=,这必须返回同一个类的对象:LIMITS_T operator = (const LIMITS_T &amp;limit) { this-&gt;min = limit.min; this-&gt;caution = limit.caution; this-&gt;max = limit.max; return *this; }

标签: c++ qt qml qt4 qt5


【解决方案1】:

您必须将属性声明为指针。根据docs

,所有 QObject 都应该作为指针进行操作

无复制构造函数或赋值运算符 QObject

没有副本 构造函数也不是赋值运算符。这是设计使然。实际上, 它们已声明,但在带有宏的私有部分中 Q_DISABLE_COPY()。事实上,所有从 QObject 派生的 Qt 类(直接 或间接)使用此宏来声明其复制构造函数和 赋值运算符是私有的。原因见于 在 Qt Object Model 页面上讨论 Identity vs Value。

主要的结果是你应该使用指向 QObject 的指针(或 您的 QObject 子类),否则您可能会想使用 您的 QObject 子类作为值。例如,没有副本 构造函数,不能使用 QObject 的子类作为值 存储在容器类之一中。您必须存储指针。

在你的情况下:

#ifndef SPLITDIALGAUGE_H
#define SPLITDIALGAUGE_H

#include "limits_t.h"

#include <QPainter>
#include <QQuickPaintedItem>    

class SplitDialGauge : public QQuickPaintedItem {
    Q_OBJECT
    Q_PROPERTY(LIMITS_T *limits READ getLimits WRITE setLimits NOTIFY limitsChanged)
    LIMITS_T *limits;    
public:
    SplitDialGauge(QQuickItem *parent = 0) : QQuickPaintedItem(parent), limits(nullptr) { }
    void paint(QPainter *painter) {
        [...]
    }    
    LIMITS_T *getLimits() const { return limits; }
    void setLimits(LIMITS_T *value) {
        if (limits == value) return;
        limits = value;
        [...]
        emit limitsChanged();
    }     
signals:
    void limitsChanged();
};
#endif // SPLITDIALGAUGE_H

可以在以下link中找到一个功能示例。

【讨论】:

  • 在这种情况下,您确实希望将指针设为空。现在它是一个悬空引用,它会传递一个 if 语句,当它被使用时程序会崩溃。还要按照惯用的方式来实现 setter - 如果新值与旧值相同,则不要做任何事情。您不想在没有实际更改的情况下发出更改通知。
猜你喜欢
  • 2018-05-24
  • 1970-01-01
  • 2014-09-22
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多