[英]How propagate an attached property to children in Qml?
我想制作類似 Material.accent 的東西,我可以在其中更改父級和子級以獲得父級屬性定義。
這是我此時所做的方式,但我無法在文檔中找到有關它的任何信息。 我知道這是可能的,Material Style 也使用這種方法和字體屬性等其他東西。
class MyThemeAttached : public QObject {
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
QML_ANONYMOUS
public:
explicit MyThemeAttached(QObject* parent = nullptr)
: QObject(parent)
, m_color("#FF0000"){}
QColor color() const;
void setColor(const QColor color);
signals:
void backgroundChanged(QColor background);
private:
QColor m_color;
};
class MyTheme : public QObject
{
Q_OBJECT
QML_ATTACHED(MyThemeAttached)
QML_ELEMENT
public:
explicit MyTheme(QObject *parent = nullptr);
static MyThemeAttached *qmlAttachedProperties(QObject *object) {
return new MyThemeAttached(object);
}
};
ApplicationWindow {
id: root
visible: true
width: 800
height: 600
title: qsTr("Window")
MyCustomProperty.color: "orange"
Rectangle {
color: MyCustomProperty.color
}
}
為什么不看一下 Material 的代碼呢? 我向您介紹 Woboq.org。
在這里你可以看到 Material 主題實際上是主動將主題推送給了孩子們:
void QQuickMaterialStyle::propagateTheme()
{
const auto styles = attachedChildren();
for (QQuickAttachedObject *child : styles) {
QQuickMaterialStyle *material = qobject_cast<QQuickMaterialStyle *>(child);
if (material)
material->inheritTheme(m_theme);
}
}
在 Qt 6.5 中,您可以為此使用QQuickAttachedPropertyPropagator 。 從文檔中:
要使用 QQuickAttachedPropertyPropagator:
- 從中得出
- 在構造函數中調用 initialize()
- 根據需要為每個屬性定義設置/繼承/傳播/重置函數
- 重新實現 attachedParentChange() 來處理屬性 inheritance
作為參考,示例中的相關文件如下。
我的風格.h :
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MYSTYLE_H
#define MYSTYLE_H
#include <QColor>
#include <QQmlEngine>
#include <QQuickAttachedPropertyPropagator>
#include "mystyle_export.h"
class MYSTYLE_EXPORT MyStyle : public QQuickAttachedPropertyPropagator
{
Q_OBJECT
// Provide a RESET function in order to allow an item to set MyStyle.theme to undefined
// in order to use its parent's (or global) theme after one was explicitly set on it.
Q_PROPERTY(Theme theme READ theme WRITE setTheme RESET resetTheme NOTIFY themeChanged FINAL)
// As the values of these properties only depend on the theme, they can all use the theme
// property's change signal.
Q_PROPERTY(QColor windowColor READ windowColor NOTIFY themeChanged FINAL)
Q_PROPERTY(QColor windowTextColor READ windowTextColor NOTIFY themeChanged FINAL)
Q_PROPERTY(QColor buttonColor READ buttonColor NOTIFY themeChanged FINAL)
Q_PROPERTY(QColor buttonTextColor READ buttonTextColor NOTIFY themeChanged FINAL)
Q_PROPERTY(QColor toolBarColor READ toolBarColor NOTIFY themeChanged FINAL)
Q_PROPERTY(QColor popupColor READ popupColor NOTIFY themeChanged FINAL)
Q_PROPERTY(QColor popupBorderColor READ popupBorderColor NOTIFY themeChanged FINAL)
Q_PROPERTY(QColor backgroundDimColor READ backgroundDimColor NOTIFY themeChanged FINAL)
QML_ELEMENT
QML_ATTACHED(MyStyle)
QML_UNCREATABLE("")
QML_ADDED_IN_VERSION(1, 0)
public:
enum Theme {
Light,
Dark
};
Q_ENUM(Theme)
explicit MyStyle(QObject *parent = nullptr);
static MyStyle *qmlAttachedProperties(QObject *object);
Theme theme() const;
void setTheme(Theme theme);
void inheritTheme(Theme theme);
void propagateTheme();
void resetTheme();
void themeChange();
QColor windowColor() const;
QColor windowTextColor() const;
QColor buttonColor() const;
QColor buttonTextColor() const;
QColor toolBarColor() const;
QColor popupColor() const;
QColor popupBorderColor() const;
QColor backgroundDimColor() const;
Q_SIGNALS:
void themeChanged();
protected:
void attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent) override;
private:
// Whether a color value was explicitly set on the specific object that this attached style object represents.
bool m_explicitTheme = false;
// The actual values for this item, whether explicit, inherited or globally set.
Theme m_theme = Light;
};
#endif // MYSTYLE_H
我的樣式.cpp :
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mystyle.h"
// If no value was inherited from a parent or explicitly set, the "global" values are used.
static MyStyle::Theme globalTheme = MyStyle::Light;
MyStyle::MyStyle(QObject *parent)
: QQuickAttachedPropertyPropagator(parent)
, m_theme(globalTheme)
{
// A static function could be called here that reads globalTheme from a
// settings file once at startup. That value would override the global
// value. This is similar to what the Imagine and Material styles do, for
// example.
initialize();
}
MyStyle *MyStyle::qmlAttachedProperties(QObject *object)
{
return new MyStyle(object);
}
MyStyle::Theme MyStyle::theme() const
{
return m_theme;
}
void MyStyle::setTheme(Theme theme)
{
// When this function is called, we know that the user has explicitly
// set a theme on this attached object. We set this to true even if
// the effective theme didn't change, because it's important that
// the user's specified value is respected (and not inherited from
// from the parent).
m_explicitTheme = true;
if (m_theme == theme)
return;
m_theme = theme;
propagateTheme();
themeChange();
}
void MyStyle::inheritTheme(Theme theme)
{
if (m_explicitTheme || m_theme == theme)
return;
m_theme = theme;
propagateTheme();
themeChange();
}
void MyStyle::propagateTheme()
{
const auto styles = attachedChildren();
for (QQuickAttachedPropertyPropagator *child : styles) {
MyStyle *myStyle = qobject_cast<MyStyle *>(child);
if (myStyle)
myStyle->inheritTheme(m_theme);
}
}
void MyStyle::resetTheme()
{
if (!m_explicitTheme)
return;
m_explicitTheme = false;
MyStyle *myStyle = qobject_cast<MyStyle *>(attachedParent());
inheritTheme(myStyle ? myStyle->theme() : globalTheme);
}
void MyStyle::themeChange()
{
emit themeChanged();
// Emit any other change signals for properties that depend on the theme here...
}
QColor MyStyle::windowColor() const
{
return m_theme == Light ? QColor::fromRgb(0xf0f0f0) : QColor::fromRgb(0x303030);
}
QColor MyStyle::windowTextColor() const
{
return m_theme == Light ? QColor::fromRgb(0x5c5c5c) : QColor::fromRgb(0xe0e0e0);
}
QColor MyStyle::buttonColor() const
{
return m_theme == Light ? QColor::fromRgb(0xc2e1ff) : QColor::fromRgb(0x74bbff);
}
QColor MyStyle::buttonTextColor() const
{
return m_theme == Light ? QColor::fromRgb(0x5c5c5c) : QColor::fromRgb(0xffffff);
}
QColor MyStyle::toolBarColor() const
{
return m_theme == Light ? QColor::fromRgb(0x4da6ff) : QColor::fromRgb(0x0066cc);
}
QColor MyStyle::popupColor() const
{
return windowColor().lighter(120);
}
QColor MyStyle::popupBorderColor() const
{
const QColor winColor = windowColor();
return m_theme == Light ? winColor.darker(140) : winColor.lighter(140);
}
QColor MyStyle::backgroundDimColor() const
{
const QColor winColor = windowColor().darker();
return QColor::fromRgb(winColor.red(), winColor.green(), winColor.blue(), 100);
}
void MyStyle::attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent)
{
Q_UNUSED(oldParent);
MyStyle *attachedParentStyle = qobject_cast<MyStyle *>(newParent);
if (attachedParentStyle) {
inheritTheme(attachedParentStyle->theme());
// Do any other inheriting here...
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.