이 게시물에서는 Qt 6.0에 추가된 C++ 바인딩 기능을 잘 사용하는 방법을 설명하고 간단한 예제를 제공한다.
다음의 간단한 클래스와 같이 QBindable<int>
를 반환하는 새로운 bindableX()
메서드를 추가하고 Q_PROPERTY
매크로에서 메타 개체 시스템에 이에 대해 알렸다. Qt 6.0부터 BINDABLE
을 사용하여 바인딩 가능한 속성을 지정할 수 있다.
myobject.h
#include <QObject>
class MyObject : public QObject
{
Q_OBJECT
Q_PROPERTY(int x READ x WRITE setX BINDABLE bindableX)
public:
explicit MyObject(QObject *parent = nullptr);
int x() { return xData; }
void setX(int x) { xData = x; }
QBindable<int> bindableX() { return &xData; }
signals:
void xChanged();
private:
// Qt5에서는 아래 줄이 "int xData;" 였다.
Q_OBJECT_BINDABLE_PROPERTY(MyObject, int, xData, &MyObject::xChanged)
};
Qt 6 이전에 setter의 구현은 새 값과 기존 값을 비교하여 다를 경우에만 클래스 멤버변수를 업데이트하고 시그널을 방출했다. Qt 6.0 이상에서는 이 동일한 기능이 한 줄만 포함하도록 단순화되었다. 현재 값과 새 값에 대한 비교가 API 코드에서 수행되기 때문이다.
바인딩을 설정하거나 알림을 등록할 수 있다. 예를 들어 다음의 예제처럼 setBinding()
호출하여 MyObject의 x 속성에 대한 바인딩을 설정한다. 또 onValueChanged()
를 통해 속성 값이 변경될 때마다 호출되는 콜백을 등록할 수 있다. 여기서는 myobject1의 x 값이 변경되면 myobject2에 설정된 바인딩을 제거하도록했다.
main.cpp
...
#include "myobject.h"
int main(int argc, char *argv[])
{
...
MyObject myobject1;
MyObject myobject2;
// 'x'프로퍼티 값 설정.
myobject1.setX(50);
// myobject1 의 'x'프로퍼티를 myobject2 의 'x'프로퍼티에 바인딩.
myobject2.bindableX().setBinding([&](){
return myobject1.x() + 50;
});
auto h1 = myobject1.bindableX().onValueChanged([&](){
qDebug() << "myobject1 'x' Changed.";
qDebug() << myobject2.bindableX().hasBinding();
// 현재 설정된 바인딩을 제거.
myobject2.bindableX().takeBinding();
qDebug() << myobject2.bindableX().hasBinding();
});
QQmlApplicationEngine engine;
...
// QML에 노출시킴.
engine.rootContext()->setContextProperty("myobject1", &myobject1);
engine.rootContext()->setContextProperty("myobject2", &myobject2);
...
}
Rectangle 의 width 는 myobject2 의 x 에 바인딩 되었으며 height 은 width 와 같다. Rectangle 영역을 마우스로 클릭하면 myobject1 의 x 값을 10 증가 시키도록했다.
main.qml
...
Rectangle {
width: myobject2.x // myobject2 의 'x'프로퍼티 바인딩.
height: width
border.width: 1
anchors.centerIn: parent
onWidthChanged: console.log("width:", width)
onHeightChanged: console.log("height:", height)
MouseArea {
anchors.fill: parent
onClicked: {
myobject1.x += 10 // myobject1의 'x'값을 10 증가시킴.
}
}
}
...
사각형을 클릭하면 시각적으로 어떻게 변하는지 알 수 있으며 콘솔 출력은 다음과 같다