英文:
Is it possible to choose between Delegates in QML using Javascript logic?
问题
目前我有一个Repeater项目,它从外部文件(PeriodicTableDelegate.qml)加载一个委托。是否可以使用JavaScript逻辑在两个不同的委托之间进行选择?也许可以像这样:
普通:
Repeater {
model: elementModel
delegate: PeriodicTableDelegate {
height: gridview.cellHeight
selectionModel: itemSelectionModel
width: gridview.cellWidth
x: (group - 1) * width
y: (period - 1) * height
}
}
我希望它能够这样工作:
Repeater {
model: elementModel
delegate: pickDelegate() ? PeriodicTableDelegate : SomeOtherDelegate {
height: gridview.cellHeight
selectionModel: itemSelectionModel
width: gridview.cellWidth
x: (group - 1) * width
y: (period - 1) * height
}
}
function pickDelegate(){
return window.height > 60
}
英文:
currently I have a Repeater Item which loads a delegate from an external file (PeriodicTableDelegate.qml). Is it possible to choose between lets say two different Delegates using Javascript logic? Maybe like this for example:
Normal :
Repeater {
model: elementModel
delegate: PeriodicTableDelegate {
height: gridview.cellHeight
selectionModel: itemSelectionModel
width: gridview.cellWidth
x: (group - 1) * width
y: (period - 1) * height
}
}
How I would want it to work:
Repeater {
model: elementModel
delegate: pickDelegate() ? PeriodicTableDelegate : SomeOtherDelegate {
height: gridview.cellHeight
selectionModel: itemSelectionModel
width: gridview.cellWidth
x: (group - 1) * width
y: (period - 1) * height
}
}
function pickDelegate(){
return window.height > 60
}
答案1
得分: 2
答案是肯定的。如评论中所提到的,有很多方法可以做到这一点,但你在问题中写的几乎已经可以工作了。唯一缺少的是你可能希望将代理声明为组件。虽然函数可以用于条件,但更合理的做法是使用属性绑定的声明式样式。
Component {
id: periodic
PeriodicTableDelegate {
// 初始化内容
}
}
Component {
id: other
SomeOtherDelegate {
// 初始化内容
}
}
property bool someCondition: window.height > 60
Repeater {
model: elementModel
delegate: someCondition ? periodic : other
}
英文:
The answer is yes. As mentioned in the comments, there are lots of ways to do it, but what you wrote in your question is already almost working. The only thing missing is you probably want to declare your delegates as Components. And while a function can work for your conditional, it makes more sense to use a declarative style relying on property bindings.
Component {
id: periodic
PeriodicTableDelegate {
// initialize stuff
}
}
Component {
id: other
SomeOtherDelegate {
// initialize stuff
}
}
property bool someCondition: window.height > 60
Repeater {
model: elementModel
delegate: someCondition ? periodic : other
}
答案2
得分: 1
以下是您提供的代码的翻译:
在运行时选择委托的方法有多种。有(1)DelegateChooser,(2)Loader,(3)QFileSelector等等。然后还有模型本身。这真的取决于情况。
在下面的应用程序中,我可以在横向或纵向模式下呈现周期表。在默认的纵向情况下,我使用“PeriodicTableDelegate.qml”进行呈现。在后一种情况下,为了适应周期表,我使用“PeriodicTableDelegateLandscape.qml”进行呈现,并将控件旋转90度。为了在这些委托之间切换,我使用了Loader.source。
我在填充ListModel时额外付出了努力,以便派生出“element”、“atomic_id”、“group”、“period”和“bkcol”。
import QtQuick
import QtQuick.Controls
Page {
id: page
Repeater {
model: periodicTable
delegate: Loader {
source: page.width >= page.height
? "PeriodicTableDelegate.qml"
: "PeriodicTableDelegatePortrait.qml"
}
}
ListModel {
id: periodicTable
property string element_definition: `H He
Li Be B C N O F Ne
Na Mg Al Si P S Cl Ar
K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr
Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe
Cs Ba La Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn
Fr Ra Ac Rf Db Sg Bh Hs Mt Ds Rg Cn Nh Fl Mc Lv Ts Og
Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu
Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr`
property var element_info: {
"He": { group: 17 },
"B": { group: 12 },
"Al": { group: 12 },
"Hf": { atomic_id: 72 },
"Ce" : { atomic_id: 58, group: 3 },
"Th" : { atomic_id: 90, group: 3, inc_period: true },
"Rf" : { atomic_id: 104 }
}
Component.onCompleted: {
let atomic_id = 1;
let group = 0;
let period = 0;
for (let element of element_definition.split(/\s+/g)) {
let info = element_info[element];
if (info) {
atomic_id = info.atomic_id || atomic_id;
group = info.group || group;
if (info.inc_period) period++;
}
let bkcol = "#246";
if (group === 0 && period) bkcol = "#255";
if (group === 1) bkcol = "#634";
if (group >= 5) bkcol = "#446";
if (group >= 12) bkcol = "#254";
if (group - period >= 12) bkcol = "#246";
if ("B,Si,Ge,As,Sb,Te,".indexOf(element + ",") >= 0) bkcol = "#542";
if (group === 17) bkcol = "#644";
if (atomic_id >= 109) bkcol = "#445";
if (period === 7) bkcol = "#047";
if (period === 8) bkcol = "#632";
append({atomic_id,group,period,element,bkcol});
++atomic_id;
if (++group === 18) {
group = 0;
period++;
}
}
}
}
}
// PeriodicTableDelegate.qml
import QtQuick
import QtQuick.Controls
Rectangle {
property int cell_width: page.width / 18
property int cell_height: page.height / 9
x: group * cell_width
y: period * cell_height
width: cell_width - 2
height: cell_height - 2
color: bkcol
Text {
anchors.centerIn: parent
text: element
color: "white"
}
Text {
x: 4
y: 4
text: atomic_id
font.pointSize: 7
color: "white"
}
}
// PeriodicTableDelegatePortrait.qml
import QtQuick
import QtQuick.Controls
Rectangle {
property int cell_width: page.width / 9
property int cell_height: page.height / 18
x: period * cell_width
y: (17 - group) * cell_height
width: cell_width - 2
height: cell_height - 2
color: bkcol
Text {
anchors.centerIn: parent
text: element
color: "white"
rotation: -90
}
Text {
x: 4
y: 4
text: atomic_id
font.pointSize: 7
color: "white"
rotation: -90
}
}
英文:
There's a number of ways of choosing a delegate at runtime. There's (1) DelegateChooser, (2) Loader, (3) QFileSelector, and so on. Then there's the model itself. It really depends.
In the following application I render the periodic table in either landscape or portrait mode. In the default portrait case, I render it with "PeriodicTableDelegate.qml". In the latter case, to fit the periodic table, I render it with "PeriodicTableDelegateLandscape.qml" and rotate the controls by 90 degrees. To switch between these delegates, I make use of Loader.source.
I spent extra effort with populating the ListModel
so that element
, atomic_id
, group
, period
and bkcol
are derived.
import QtQuick
import QtQuick.Controls
Page {
id: page
Repeater {
model: periodicTable
delegate: Loader {
source: page.width >= page.height
? "PeriodicTableDelegate.qml"
: "PeriodicTableDelegatePortrait.qml"
}
}
ListModel {
id: periodicTable
property string element_definition: `H He
Li Be B C N O F Ne
Na Mg Al Si P S Cl Ar
K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr
Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe
Cs Ba La Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn
Fr Ra Ac Rf Db Sg Bh Hs Mt Ds Rg Cn Nh Fl Mc Lv Ts Og
Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu
Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr`
property var element_info: {
"He": { group: 17 },
"B": { group: 12 },
"Al": { group: 12 },
"Hf": { atomic_id: 72 },
"Ce" : { atomic_id: 58, group: 3 },
"Th" : { atomic_id: 90, group: 3, inc_period: true },
"Rf" : { atomic_id: 104 }
}
Component.onCompleted: {
let atomic_id = 1;
let group = 0;
let period = 0;
for (let element of element_definition.split(/\s+/g)) {
let info = element_info[element];
if (info) {
atomic_id = info.atomic_id || atomic_id;
group = info.group || group;
if (info.inc_period) period++;
}
let bkcol = "#246";
if (group === 0 && period) bkcol = "#255";
if (group === 1) bkcol = "#634";
if (group >= 5) bkcol = "#446";
if (group >= 12) bkcol = "#254";
if (group - period >= 12) bkcol = "#246";
if ("B,Si,Ge,As,Sb,Te,".indexOf(element + ",") >= 0) bkcol = "#542";
if (group === 17) bkcol = "#644";
if (atomic_id >= 109) bkcol = "#445";
if (period === 7) bkcol = "#047";
if (period === 8) bkcol = "#632";
append({atomic_id,group,period,element,bkcol});
++atomic_id;
if (++group === 18) {
group = 0;
period++;
}
}
}
}
}
// PeriodicTableDelegate.qml
import QtQuick
import QtQuick.Controls
Rectangle {
property int cell_width: page.width / 18
property int cell_height: page.height / 9
x: group * cell_width
y: period * cell_height
width: cell_width - 2
height: cell_height - 2
color: bkcol
Text {
anchors.centerIn: parent
text: element
color: "white"
}
Text {
x: 4
y: 4
text: atomic_id
font.pointSize: 7
color: "white"
}
}
// PeriodicTableDelegatePortrait.qml
import QtQuick
import QtQuick.Controls
Rectangle {
property int cell_width: page.width / 9
property int cell_height: page.height / 18
x: period * cell_width
y: (17 - group) * cell_height
width: cell_width - 2
height: cell_height - 2
color: bkcol
Text {
anchors.centerIn: parent
text: element
color: "white"
rotation: -90
}
Text {
x: 4
y: 4
text: atomic_id
font.pointSize: 7
color: "white"
rotation: -90
}
}
You can Try it Online!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论