在QML中是否可以使用JavaScript逻辑来选择委托?

huangapple go评论76阅读模式
英文:

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
    }
}

您可以在[此处在线尝试](https://stephenquan.github.io/qmlonline/?zcode=AAANR3ic1VZrb+JGFP3uX3HkSitYHEJYskkcpRU4D6IFwoL72G2rrLHHZhTbQ8fDbtJd/nvHL7AxJO2Hquooijxzz32fGS4NFowLvBfvl9R+UGhp2zRYKDjzI2VseQRfFchFHR0LuU02E7IgliA8k8UrYA7xJYRwyhxqm9bMJ2uhFBFPKugYMMsp6cUrYktuk9R+8wt1xBzfX6S7OaHeXJTQP0AdF71cZsabfwS+WkLqe5BjmSy3qChrrJTN/wGNxDDOqBBpUoGd6S04kwLxhEhwGnqQbgISinuHuDSkgrJQx6c++kQZUPQIejAwwh2uMSLKyMLQQ9fHlGKMKQwfXa68g2FhasOk+AkGxzDENYHBMKIwlvgY4sbCDUE3wlQa5HjHlckMU44P+MgxmmHIYNqYLDGZY+yg68FwcBtiKv9mMAlu8QtRjAg9CwMLfRemhZ9la3EX4ZZjLNBdou/B9DGeoSejY

英文:

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!

huangapple
  • 本文由 发表于 2023年5月26日 16:14:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76338916.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定