web-dev-qa-db-ja.com

QML-JavaScriptから設定できるようにQMLコンポーネントプロパティを作成する方法

設定した特定のプロパティを持つコンポーネントを作成しようとしています。サウンドの場所と名前は、console.log()に次のように表示されるため、実際に動作しているC++関数によって指定されます。

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

問題は、プロパティをListElementに設定しようとすると、プロパティが認識されなかったかのように、ListViewを空のままにしてしまうことです。

ファイル内のJavasCript関数は次のとおりです。

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());
}

使用されるページは次のとおりです。

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

リストセレクターに使用されるコンポーネントは次のとおりです。これは、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")
        }
    }
}

そして、JSファイルで使用されるNameプロパティとSoundプロパティを定義するListElementは次のとおりです。

ListElement {
    id: soundsListElement
    objectName: "soundsListElement"

    property string Name
    property string Sound

    name: Name
    sound: Sound
}

私の問題は、JSはNameとSoundがListElementの文字列プロパティであることを理解していないようであり、ListViewコンポーネントに存在する関数で指定されたsoundNameとsoundLocationでそれらを設定する必要があるためですページ。代わりに、アイテムセレクターは完全に空になります。

私が間違っていることを見つけることができません。どんな助けでも大歓迎です。

here の例に従ったと思いますが、あなたの場合はconnectcomponent.statusChanged信号にしようとしていますが、同時にfinishCreationハンドラーは引数を受け入れます。不可能です。

シグナルに接続されると、送信されると、finishCreationを引数なしで呼び出します。空のアイテムが表示される理由はこれで説明できると思います。

シグナルハンドラーが呼び出されたときに、soundNamesoundLocationの両方にアクセスできるようにするには、jsファイルのcomponentelementのようにグローバルにします(未テスト) :

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

それを修正しました。 ListElementコンポーネントを作成すべきではないようです。代わりに、ListModelは次のようになります。

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

JavaScriptファイルは次のようになります。

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

リストに追加する必要があります。