В приложении 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)
}





Вы не можете этого сделать, но можете создать собственный компонент и повторно использовать новый тип. [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 Насколько я понимаю ваш вопрос, вы хотите повторно использовать некоторые предопределенные свойства для компонента. Лучший способ сделать это в QML — определить новый тип, как описано выше. Однако использовать последнее решение не рекомендуется, поскольку оно не является ни декларативным, ни очень чистым.
@ElevenJune Кроме того, используя initImgLayout, вы не сможете создавать привязки так же легко, как в декларативном решении.
Хорошо ! Я знаю, понимаю, почему это плохое решение!
Хочу выделить Img.qml аспект ответа смр.
В крупных проектах QML ищите способы уменьшить сложность с помощью компонентов. Я часто подклассифицирую компоненты QML со свойствами, адаптированными для моего приложения.
В следующей демонстрации я решил сделать:
AppText — это персонализация TextAppHeading1 — это персонализация AppTextAppHeading2 — это персонализация AppTextAppImage — это персонализация ImageAppPage — это настройка 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>
Вы можете Попробовать онлайн!
Спасибо за Ваш ответ ! Я тоже так делаю, как и вы, например, с Текстом. Что я забыл сказать в своем посте, так это то, что даже при использовании пользовательского компонента ширина и высота по-прежнему варьируются в зависимости от экрана. Мне нужно указать ширину и высоту каждого пользовательского компонента.
Большое спасибо за ваш ответ ! Мне больше всего нравится последний, но почему бы вам не порекомендовать его?