Qt 属性语法的正确使用

2023-12-19

当我使用Q_PROPERTY要定义一个属性,我确保继承自QObject并声明Q_OBJECT宏位于类定义的开头。我这样声明属性:

Q_PROPERTY(QString MyProp READ getMyProp WRITE setMyProp)

然后我这样使用它:

myObject->MyProp = QString("test");

它告诉我没有这样的成员MyProp。问题是什么?


当然没有这样的成员,因为您自己已经说过吸气剂被称为getMyProp,设置器被称为setMyProp。成员的定义称为MyProp完全取决于你。下面,我将展示如何定义此类成员。

我们还应该注意到,在 Qt 中,习惯上不要在 getter 前面加上get,但只需以属性命名即可。这样你就有了

Q_PROPERTY(int foo READ foo WRITE setFoo)
// rather than
Q_PROPERTY)int foo READ getFoo WRITE setFoo)

可能的解决方案包括:

(1) 直接访问属性的数据成员 - 这会破坏属性系统授予的封装性,并且不建议这样做。

class Direct : public QObject {
  Q_OBJECT
  Q_PROPERTY(int prop MEMBER prop)
public:
  int prop;
};

Direct d;
d.prop = 3;
Q_ASSERT(d.property("prop").toInt() == 3);

最后一行有效是因为moc生成简单的 getter 和 setter 代码,然后可以通过元对象系统访问这些代码。此代码嵌入在元数据实现中,不会导致任何方法添加到类本身。

(2) 有一个返回引用的 getter。当 getter 和 setter 很简单时,这是最简单、低开销的方法。

class GetSet : public QObject {
  Q_OBJECT
  Q_PROPERTY(int prop READ prop WRITE setProp)
  int m_prop;
public:
  int & prop() { return m_prop; }
  int prop() const { return m_prop; }
  void setProp(int prop) { m_prop = prop; }
};

GetSet gs;
gs.prop() = 3; // assignment syntax through "getter"
Q_ASSERT(gs.property("prop").toInt() == 3);
gs.setProp(4); // setter syntax
Q_ASSERT(gs.property("prop").toInt() == 4);

(3) 公开充当财产代理的成员。这允许在没有调用语法的情况下使用代理:obj.prop代替obj.prop().

(3a) 我们可以使用 Qt 属性系统来访问命名属性。这QMetaProperty充当缓存以避免每次属性访问时重复名称查找。 AQVariant对每个属性访问执行转换。

template <typename B, typename T> class PProxy {
  Q_DISABLE_COPY(PProxy)
  B * obj;
  QMetaProperty prop;
public:
  PProxy(B & o, const char * p) : obj(&o), 
    prop(o.metaObject()->property(o.metaObject()->indexOfProperty(p))) {}
  T operator=(const T & val) { prop.write(obj, val); return val; }
  T operator=(T && val) { prop.write(obj, val); return val; }
  operator T() const { return prop.read(obj).value<T>(); }
};

class ViaPProxy : public QObject {
  Q_OBJECT
  Q_PROPERTY(int prop READ getProp WRITE setProp)
  int m_prop;
public:
  PProxy<Direct, int> prop;
  ViaPProxy() : prop(*this, "prop") {}
  int getProp() const { return m_prop; }
  void setProp(int val) { m_prop = val; }
}

ViaPProxy vpp;
vpp.prop = 3; // invokes the setter through a proxy
Q_ASSERT(vpp.prop == 3);

(3b) 而不是通过 Qt 属性系统QVariant转换时,代理可以直接使用 getter 和 setter。这比 (3a) 的开销更低,但要求存在 getter 和可选的 setter。

template <typename B, typename T, 
          T (B::*get)() const, void (B::*set)(T) = 0> class DProxy {
  Q_DISABLE_COPY(DProxy)
  B & obj;
public:
  DProxy(B & o) : obj(o) {}
  T operator=(const T & val) { (obj.*set)(val); return val; }
  T operator=(T && val) { (obj.*set)(std::forward<T>(val)); return val; }
  operator T() const { return (obj.*get)(); }
};

class ViaDProxy : public QObject {
  Q_OBJECT
  Q_PROPERTY(int prop READ getProp WRITE setProp)
  int m_prop;
public:
  DProxy<Direct, int, &ViaDProxy::get, &ViaDProxy::set> prop;
  ViaDProxy() : prop(*this) {}
  int getProp() const { return m_prop; }
  void setProp(int val) { m_prop = val; }
}

ViaDProxy vdp;
vdp.prop = 3; // invokes the setter through a proxy
Q_ASSERT(vdp.prop == 3);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt 属性语法的正确使用 的相关文章

随机推荐

  • 在wxPython中查找文本大小的正确方法

    我正在使用 wxPython 开发一个应用程序 该应用程序的一部分在网格中创建大量 TextCtrl 以便为任意大的人员列表输入一周中的每一天的四字母代码 我已经设法让它发挥作用 但我不得不做一些笨拙的事情 具体来说 我还没有找到一种好的方
  • 网络音频 api 以不同的速率播放嘟嘟声、嘟嘟声、...嘟嘟声

    我试图根据浏览器窗口内的一些传感器读数以不同的速率播放 嘟嘟 声 这个想法是当传感器读数高时更快地 嘟嘟 嘟嘟 嘟 嘟 当传感器读数低时更慢地 嘟 嘟 所有这些都是实时的 传感器读数通过 socket io 输入浏览器 我已经可以控制进度条
  • JS 中的数独求解器

    我正在尝试编写一种可以解决数独的算法 目前 我的代码可以正常工作 直到 SupplyGrid 的数量耗尽为止 当这种情况发生时 它应该返回并尝试另一个号码 对吧 老实说 我不知道如何实现这一目标 var grid 0 0 0 0 0 0 0
  • Android:使用repeatWhen、takeUntil和带改造的过滤器通过rx-java无限滚动

    我正在使用 Retrofit 2 2 和 RxJava 分页是这样工作的 我得到第一批数据 我必须请求具有相同参数的第二批数据 除了最后更新日期 然后如果我得到空或同一批数据 则意味着有没有更多的物品 我发现了这篇很棒的文章https me
  • 如何在 jQuery/Javascript 中逐点获取元素

    我想通过指定页面中的点值来获取元素 var point this svgRenderer getPoint serPoint chart 这将返回页面的精确点位置 该点包含一些 SVG 元素 可以是圆形 矩形 图像或其他元素 我想根据点位置
  • 无法在 cmakelists.txt 中使用 protobuf

    我正在尝试运行 protobuf repo 中给出的示例here https github com google protobuf tree master examples c 版本 我已经成功安装了该库并且能够运行Makefile 但在运
  • 三重感叹号的使用

    查看我们一个项目的源代码 我发现我们在条件语句中使用了三个感叹号的一些地方 如下所示 if someVar 现在 我明白这不是某种很少使用的运算符 它只是连续三个否定 例如 someVar 我不明白它有什么用 在我看来它可以安全地用单个感叹
  • Qt 中 QMainWindow 上的深色透明层

    我需要在我的应用程序中实现一个 正在加载 窗口 但我更喜欢用上面有文本的深色透明层覆盖整个 QMainWindow 有人知道该怎么做吗 我不知道如何在 Qt 中重叠小部件 布局 任何帮助将不胜感激 这个答案位于我的一系列与覆盖相关的答案中
  • 无法在 Windows 10 和 Python 3.7 上安装 dlib

    我正在尝试在 Windows 10 上的 Anaconda Python 3 7 上安装 OpenCV dlib 我已经安装了 Visual studio 2015 作为先决条件以及 CMake 当我尝试在计算机上安装 dlib 时 出现以
  • Android Studio 中未处理的异常 Class.forname("com.google.cloud.sql.jdbc.Driver")

    我在 Android Studio 中有一个项目谷歌云端点模块 我正在尝试将我的端点模块连接到一个实例谷歌云SQL我在同一个项目中拥有的 在 IDE 中我看到以下错误 Unhandled exception java lang ClassN
  • C++ 变量名前的“ :: ”

    include
  • Android从服务器下载图像并保存到SD卡而不使用BitmapFactory

    我正在尝试创建一个用于从服务器下载图像并将其显示到列表视图中的应用程序 我遇到的问题是内存泄漏并使我的应用程序崩溃 我在 Android 博客中搜索这样的link http android developers blogspot com 2
  • 在 Chrome 29+ 中使用 CSS 变量

    我的 Chrome 浏览器刚刚从版本 28 切换到版本 29 切换后 我的 css3 代码在新版本中停止工作 我想知道是否有人知道如何解决该问题 而无需将我的浏览器设置回版本 28 更新 Chrome 30从 Chrome 29 过渡到 C
  • 根据一列获取两个数据表之间的差异

    我有以下场景 表 A 有 50 条记录 表 B 有 2 条记录 我需要定义一个新表 例如 TableDiff 它应包含表 A 中不存在于表 B 中的 48 条记录 我的问题是表 A 和表 B 不相同 但我有该字段rowId它存在于我需要使用
  • 在 Dart 中测试 unicode 字素簇相等性?

    像 这样的 unicode 字符可以通过两种方式表示为 UTF16 字符串 Dart 的本机实现 u00e9 u0065 u0301 e 组合变音符号 由于它们内部不同 测试字符串或符文的相等性将表明它们不相等 print u00e9 u0
  • 如何在Google排行榜中默认打开“全部”而不是“社交”?

    我已将 Google 排行榜集成到我的 Android 游戏应用程序中 当我打开它时 它默认进入 社交 模式 又名我的谷歌圈子 我需要手动切换到 全部 模式 来自世界各地的玩家 如何将 全部 模式设置为默认模式 有一个重载方法 它接受所有参
  • Angular 5 Http Interceptors 注入服务时出错

    在 Angular 5 中使用自定义 HttpInterceptors 时 我收到以下奇怪的依赖注入行为 下面的简化代码可以正常工作 export class AuthInterceptor implements HttpIntercept
  • 类“QueryDocumentSnapshot”没有实例方法“[]”。接收者:“QueryDocumentSnapshot”的实例尝试调用:[](“名称”)

    我正在尝试从 FireStore 检索这两个值 姓氏 test 字符串 姓名 Carlos 字符串 但是我收到这个错误 Another exception was thrown NoSuchMethodError Class QueryDo
  • ios10 iphone5s voip siphon pjsip2.5.5 打开声音设备时出错

    有人可以告诉我为什么会发生这种情况吗 iOS10 iPhone5s VOIP虹吸pjsip2 5 5 这些问题并不是每次都会出现 有时当你想拨打电话或接听电话时就会出现 添加于 20161226 打开声音设备时出错 14 06 03 137
  • Qt 属性语法的正确使用

    当我使用Q PROPERTY要定义一个属性 我确保继承自QObject并声明Q OBJECT宏位于类定义的开头 我这样声明属性 Q PROPERTY QString MyProp READ getMyProp WRITE setMyProp