web-dev-qa-db-fra.com

QML - Comment créer des propriétés de composants QML afin qu'elles puissent être définies à partir de JavaScript?

J'essaie de créer un composant avec certaines propriétés que j'ai définies. L'emplacement et le nom des sons sont donnés par une fonction C++ qui fonctionne car le fichier console.log () l'indique ainsi:

qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Amsterdam.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Blip.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Mallet.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Positive.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Rhodes.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Slick.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Soft delay.ogg sound
qml: Adding /home/vitimiti/.local/share/com.ubuntu.developer.vitimiti.irc-app/sounds/Xylo.ogg sound

Le problème est que, lorsque vous essayez de définir les propriétés sur un ListElement, il laissera simplement le ListView vide, comme s'il ne reconnaissait pas les propriétés.

Voici mes fonctions JavasCript dans un fichier:

var component;
var element;

function createElement(soundName, soundLocation) {
    component = Qt.createComponent("../AlertsSettingsSounds.qml")
    if (component.status === Component.Ready)
        finishCreation(soundName, soundLocation)
    else
        component.statusChanged.connect(finishCreation)
}

function finishCreation(soundName, soundLocation) {
    if (component.status === Component.Ready) {
        element = component.createObject(alertsModel, {
                                             "Name": soundName,
                                             "Sound": soundLocation});

        if (element === null)
            // Error Handling
            console.log("Error creating object");
    } else if (component.status === Component.Error)
        // Error Handling
        console.log("Error loading component: ", component.errorString());
}

Voici la page qui est utilisée:

import QtQuick 2.0
import Ubuntu.Components 1.1
import Ubuntu.Components.ListItems 1.0 as ListItem

import Irc_App 0.1

import "../components"

// Mobile (small screen) layout
Page {
    id: alertsSettingsPage
    objectName: "alertSettingsPage"

    title: i18n.tr("Alerts")

    Row {
        id: muteRow
        objectName: "muteRow"

        anchors {
            left: parent.left
            leftMargin: root.margins
            top: parent.top
            topMargin: root.margins
            right: parent.right
            rightMargin: root.margins
        }

        spacing: root.spacing

        Label {
            id: muteLabel
            objectName: "muteLabel"

            width: parent.width - muteCheckBox.width

            text: i18n.tr("<b>Mute</b> notifications")
        }

        CheckBox {
            id: muteCheckBox
            objectName: "muteCheckBox"

            checked: false
            onCheckedChanged: {
                if (checked === true)
                    soundsComponent.volume = 0
                else
                    soundsComponent.volume = 1
            }
        }
    }

    Flickable {
        id: soundsFlickable
        objectName: "soundsFlickable"

        anchors {
            left: parent.left
            leftMargin: root.margins
            top: muteRow.bottom
            right: parent.right
            rightMargin: root.margins
            bottom: parent.bottom
            bottomMargin: root.margins
        }

        clip: true
        contentHeight: soundsColumn.height
        contentWidth: parent.width
        flickableDirection: Flickable.VerticalFlick

        Column {
            id: soundsColumn
            objectName: "soundsColumn"

            width: parent.width
            spacing: root.spacing

            // One item selector for each notification there is.
            ListItem.ItemSelector {
                id: highlightAlertSelector
                objectName: "highlightAlertSelector"

                text: i18n.tr("Highlight Alert")
                expanded: false
                model: alertsSettingsComponent

                onSelectedChanged: {
                    console.log(selectedIndex + " selected")
                }

                delegate: OptionSelectorDelegate {
                    text: name
                    onClicked: {
                        // This functions are local and to make the alerts
                        // sound as they ought to. They will write the
                        // configuration to the xml file and, from there,
                        // the program will start with those options set
                        // and the events will read such file to set again the
                        // Audio component and make it work for just the event.
                        if (name === "Muted") {
                            console.log("Muting sound for highlights")
                            soundsComponent.source = ""
                        } else {
                            console.log("Starting sound " + name +
                                        " for highlights")
                            console.log("Setting sound option " + name +
                                        " for highlights")
                            soundsComponent.source =
                                    soundsHandler.soundsLocation + "/" + name
                            soundsComponent.play()
                        }
                    }
                }

                Component.onCompleted: {
                    // Set the muteCheckBox as it is in the configuration
                    // Set the sounds as they are in the configuration file
                }
            }

            ListItem.ItemSelector {
                id: kickedAlertsSelector
                objectName: "kickedAlertsSelector"

                text: i18n.tr("Kicked Alert")
                expanded: false
                model: alertsSettingsComponent

                onSelectedChanged: {
                    console.log(selectedIndex + " selected")
                }

                delegate: OptionSelectorDelegate {
                    text: name
                    onClicked: {
                        if (name === "Muted") {
                            console.log("Muting sound for kicked event")
                            soundsComponent.source = ""
                        } else {
                            console.log("Starting sound " + name +
                                        " for kicked event")
                            console.log("Setting sound option " + name +
                                        " for kicked event")
                            soundsComponent.source =
                                    soundsHandler.soundsLocation + "/" + name
                            soundsComponent.play()
                        }
                    }
                }

                Component.onCompleted: {
                    // Set the muteCheckBox as it is in the configuration
                    // Set the sounds as they are in the configuration file
                }
            }
        }
    }

    AlertsSettingsComponent {
        id: alertsSettingsComponent
        objectName: "alertsSettings_component"
    }

    SoundsComponent {
        id: soundsComponent
        objectName: "sounds_component"
    }
}

Voici le composant utilisé pour les sélecteurs de liste, celui qui devrait fonctionner avec les fonctions JS:

import QtQuick 2.0

import Irc_App 0.1

import "../js/AlertsSettingsFunctions.js" as AlertsSettingsFunction

// Using the sounds from the folder
ListModel{
    id: alertsModel
    objectName: "alertsModel"

    Component.onCompleted: {
        for (var i = 0; i < soundsHandler.sounds.length; i++) {
            AlertsSettingsFunction.createElement(soundsHandler.sounds[i],
                        soundsHandler.soundsLocation + "/"
                        + soundsHandler.sounds[i])
            console.log("Adding", soundsHandler.soundsLocation + "/"
                        + soundsHandler.sounds[i], "sound")
        }
    }
}

Et voici le ListElement qui définit les propriétés Name et Sound utilisées dans le fichier JS:

ListElement {
    id: soundsListElement
    objectName: "soundsListElement"

    property string Name
    property string Sound

    name: Name
    sound: Sound
}

Donc, mon problème est que le JS ne semble pas comprendre que Name et Sound sont des propriétés de chaîne pour ListElement et qu'il doit les définir avec le soundName et soundLocation donnés dans la fonction présente dans le composant ListView, de manière à l'afficher dans la page. Au lieu de cela, les sélecteurs d’éléments apparaissent complètement vides.

Je ne peux pas savoir ce que je fais mal, toute aide serait très appréciée.

Je pense que vous avez suivi l'exemple donné ici , mais dans votre cas, vous essayez de connect au signal component.statusChanged et vous attendez en même temps à voir le finishCreation gestionnaire pour accepter les arguments. Ce n'est pas possible.

Une fois connecté au signal, s'il est émis, il appellera finishCreation sans arguments. Je suppose que cela explique pourquoi vous voyez des objets vides.

Pour vous assurer que lorsque le gestionnaire de signal est appelé, vous avez accès à la fois à soundName et à soundLocation, je les rendrais globaux, comme component et element dans le fichier js (non testé). :

var component;
var element;
var _soundName;
var _soundLocation;

function createElement(soundName, soundLocation) {
    component = Qt.createComponent("../AlertsSettingsSounds.qml")
    _soundName = soundName
    _soundLocation = soundLocation
    if (component.status === Component.Ready)
        finishCreation()
    else
        component.statusChanged.connect(finishCreation)
}

function finishCreation() {
    if (component.status === Component.Ready) {
        element = component.createObject(alertsModel, {
                                             "Name": _soundName,
                                             "Sound": _soundLocation});

        if (element === null)
            // Error Handling
            console.log("Error creating object");
    } else if (component.status === Component.Error)
        // Error Handling
        console.log("Error loading component: ", component.errorString());
}
2
Sylvain Pineau

Fixe le. Il semble que je ne devrais pas créer un composant ListElement. Au lieu de cela, le ListModel devrait ressembler à ceci:

import QtQuick 2.0

import Irc_App 0.1

import "../js/AlertsSettingsFunctions.js" as AlertsSettingsFunction

// Using the sounds from the folder
ListModel {
    id: alertsModel
    objectName: "alertsModel"

    Component.onCompleted: {
        for (var i = 0; i < soundsHandler.sounds.length; i++)
            AlertsSettingsFunction.makeList(alertsModel,
                                            soundsHandler.sounds[i],
                                            soundsHandler.soundsLocation + "/"
                                            + soundsHandler.sounds[i])
    }
}

Et le fichier JavaScript devrait ressembler à:

function makeList(id, soundName, soundLocation) {
    id.append({"name" : soundName, "sound" : soundLocation})
}

Il devrait être ajouté à la liste.