Qt - UI数据双向绑定简易实现

乍暖还寒时候,与上班提醒互道早安。

前言

自从前端大火了以后,UI数据双向绑定的ui框架愈发流行。作为前菜鸡安卓开发,我也是最近才知道谷歌还有推 Jetpack Compose 作为UI框架;其最大的亮点就是 数据双向绑定声明式UI。而作为现Qt开发,看到声明式UI的使用表示简直不要太爽啊!

实现声明式UI ≈ 实现一个 编译器,非我等俗人可简单实现。那就退而求其次,先用Qt实现 UI与·数据双向绑定

原理

查找了一下,实现数据绑定的做法有大致如下几种:

  • 发布者-订阅者模式
  • 脏值检查
  • 数据劫持

Qt 实现思路

首先明确我们需要实现什么:

实现一个UI组件,这个组件可实现数据双向绑定。我们更新绑定变量的时候,绑定这个变量的UI组件,数据也会同步更新。同理,我们直接修改UI组件的属性,例如滑动条的位置亦会同步修改变量值。

Qt - 一文理解信号槽机制(万字剖析整理) 中讲到 Qt的信号槽机制就有用到 发布-订阅模型。那么我们将通过信号槽实现。

随着而来的是,信号槽机制依赖于 QObject元对象系统。而我们绑定的变量可能是 intfloat之类。为了能使用信号槽的通讯机制,我们必须将基本数据类型再封装一次。然后在变量类改变时通知控件类,在控件类改变时通知变量类。

在Qt中,控件类的改变本身就有相应的 changed() 信号,所以我们只需要接起来即可。

接下来的问题是如何知晓变量类改变,答案是 重载赋值运算符

源码

/*! hslider.h */
#ifndef HSLIDER_H
#define HSLIDER_H

#include <QWidget>
#include <QSlider>
#include <QDebug>

class HInt : public QObject
{
    Q_OBJECT
public:
    explicit HInt(int x = 0){number = x;}
    void operator=(const HInt &newValue )
    { Q_EMIT(change(newValue.number)); number = newValue.number;}
signals:
   void change(int newValue);
public slots:
   void update(int newValue){ number = newValue; qDebug() << "HInt::update: " << newValue;}
private:
    int number;
};

class HSlider : public QWidget
{
    Q_OBJECT
public:
    explicit HSlider(QWidget *parent = nullptr);
    void Buid(HInt *newValue);
signals:
   void change(int newValue);
public slots:
    void update(int newValue);
private:
    QSlider* mSlider;
    HInt *mValue;
};

#endif // HSLIDER_H


/*! hslider.cpp */
#include "hslider.h"

HSlider::HSlider(QWidget *parent) : QWidget(parent)
{
    mSlider = new QSlider(this);
    connect(mSlider,&QSlider::valueChanged,this,&HSlider::change);
}

void HSlider::Buid(HInt *newValue){
    if(newValue){
        if(!mValue){
            disconnect(mValue,&HInt::change,this,&HSlider::update);
            disconnect(this,&HSlider::change,mValue,&HInt::update);
        }
        mValue = newValue;
        connect(mValue,&HInt::change,this,&HSlider::update);
        connect(this,&HSlider::change,mValue,&HInt::update);
    }
}

void HSlider::update(int newValue){
    mSlider->setValue(newValue);
    qDebug() << "HSlider::update" << newValue;
}

效果

在这里插入图片描述

一些想法

  • 这是一个简陋的封装及演示,有时候应该参考 QSlider 的实现自定义控件。
  • HInt 用起来让人很不爽,可能得找找有没有别的什么办法能监控到变量的改变(并不想用事件轮询)。或许我应该好好了解下 数据劫持脏值检查 看能不能找到一些实现思路。

参考鸣谢

Vue.js数据双向绑定实现

C++ 赋值运算符重载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值