Как динамически генерировать атрибуты для элемента QML?

В приложении QML, которое я пишу, я всегда пишу одни и те же имена атрибутов с разными значениями. Например :

Image{
    source:"qrc:/..."
    Layout.preferredWidth: 124 //Always
    Layout.preferredHeight: 229 //the same
    Layout.alignment: Qt.AlignHCenter //3 lines
    Layout.topMargin: convertHeight(40)
    Layout.bottomMargin: convertHeight(26)
}

можно ли определить функцию, которая генерирует динамические атрибуты:

function sizeProps(width,height){
    return {
        Layout.preferredWidth : width,
        Layout.preferredHeight : height,
        Layout.alignment: Qt.AlignHCenter
    }
}

и использовать такие динамически генерируемые атрибуты?

Image{
    source:"qrc:/..."
    {sizeProps(124,229)}
    Layout.topMargin: convertHeight(40)
    Layout.bottomMargin: convertHeight(26)
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы не можете этого сделать, но можете создать собственный компонент и повторно использовать новый тип. [1]

Либо определив встроенный компонент , например:

component Img: Image {
    property size size: Qt.size(width, height)  /* default value */

    Layout.preferredWidth: size.width
    Layout.preferredHeight: size.height
    Layout.alignment: Qt.AlignHCenter
}

// usage: 
Img { size{width: 100; height: 200} }

Или определить его в отдельном .qml файле [3].

Изображение.qml

Image {
    property size size: Qt.size(width, height)
    
    Layout.preferredWidth: size.width
    Layout.preferredHeight: size.height
    Layout.alignment: Qt.AlignHCenter
}

// usage: (same as inline component)
Img { size{width: 100; height: 200} }

Но если вы предпочитаете использовать функции, вы тоже можете это сделать, но я не рекомендую это делать.

function initImgLayout(item, width, height) {
    item.Layout.preferredWidth = width;
    item.Layout.preferredHeight = height;
    item.Layout.alignment = Qt.AlignHCenter;
}

Image {
    Component.onCompleted: initImgLayout(this, 100, 200);
}

Большое спасибо за ваш ответ ! Мне больше всего нравится последний, но почему бы вам не порекомендовать его?

ElevenJune 26.02.2024 10:33

@ElevenJune Насколько я понимаю ваш вопрос, вы хотите повторно использовать некоторые предопределенные свойства для компонента. Лучший способ сделать это в QML — определить новый тип, как описано выше. Однако использовать последнее решение не рекомендуется, поскольку оно не является ни декларативным, ни очень чистым.

smr 26.02.2024 12:48

@ElevenJune Кроме того, используя initImgLayout, вы не сможете создавать привязки так же легко, как в декларативном решении.

smr 26.02.2024 12:52

Хорошо ! Я знаю, понимаю, почему это плохое решение!

ElevenJune 26.02.2024 14:18

Хочу выделить Img.qml аспект ответа смр.

В крупных проектах QML ищите способы уменьшить сложность с помощью компонентов. Я часто подклассифицирую компоненты QML со свойствами, адаптированными для моего приложения.

В следующей демонстрации я решил сделать:

  • AppText — это персонализация Text
    • AppHeading1 — это персонализация AppText
    • AppHeading2 — это персонализация AppText
  • AppImage — это персонализация Image
    • Сюда входят все ваши настройки
  • AppPage — это настройка Page в сочетании с ScrollView и ColumnLayout.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
AppPage {
    title: "AppImage Example"
    AppHeading1 { text: "AppImage Example" }
    AppHeading2 { text: "Red Circle" }
    AppImage { source: "red-circle.svg" }
    AppHeading2 { text: "Green Triangle" }
    AppImage { source: "green-triangle.svg" }
}

// AppPage.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    default property alias data: columnLayout.data
    ScrollView {
        id: scrollView
        anchors.fill: parent
        ScrollBar.vertical {
            policy: ScrollBar.AlwaysOn
            width: 20
        }
        ColumnLayout {
            id: columnLayout
            width: scrollView.width - 20
        }
    }
}

// AppText.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Text {
    Layout.alignment: Qt.AlignHCenter
}

// AppHeading1.qml
import QtQuick.Layouts
AppText {
    Layout.topMargin: 10
    font.pointSize: 20
    font.bold: true
    color: "blue"
}

// AppHeading2.qml
import QtQuick.Layouts
AppText {
    Layout.topMargin: 10
    font.pointSize: 14
    color: "orange"
}

// AppImage.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Image {
    Layout.preferredWidth: 124
    Layout.preferredHeight: 229
    Layout.alignment: Qt.AlignHCenter
    Layout.topMargin: convertHeight(40)
    Layout.bottomMargin: convertHeight(26)
    cache: false
    function convertHeight(h) {
        return h;
    } 
}

// red-circle.svg
<svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 124 229">
<rect width = "124" height = "229" fill = "lightblue" />
<circle cx = "62" cy = "115" r = "30" fill = "red" />
</svg>

// green-triangle.svg
<svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 124 229">
<rect width = "124" height = "229" fill = "lightblue" />
<path d = "M 62 85 L 92 145 L 32 145 Z" fill = "green" />
</svg>

Вы можете Попробовать онлайн!

Спасибо за Ваш ответ ! Я тоже так делаю, как и вы, например, с Текстом. Что я забыл сказать в своем посте, так это то, что даже при использовании пользовательского компонента ширина и высота по-прежнему варьируются в зависимости от экрана. Мне нужно указать ширину и высоту каждого пользовательского компонента.

ElevenJune 26.02.2024 10:35

Другие вопросы по теме