Home > OS >  Qt5 QML - Set component of Loader as an argument problem
Qt5 QML - Set component of Loader as an argument problem

Time:01-31

I'm looking for how to input for Loader inside Component. Here is my problem.

// CustomSplitView.qml
import QtQuick 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.14

Pane {
  function addItem(text, item) {
    /**
      Here is the problem part I think.
      "headerText" is correctly applied to the 'template' object, 
      but "content" is not.
    **/
    splitView.addItem(template.createObject(null, {"headerText": text, "content": item}))
  }
  Component {
    id: template
    Pane {
      property alias headerText: label.text
      property alias content: loader.sourceComponent
      ColumnLayout { anchors.fill: parent
        Label { id: label }
        Loader {
          id: loader
          Layout.fillWidth: true; Layout.fillHeight: true
          sourceComponent: Rectangle { color: "Green" }
        } // Loader
      } // ColumnLayout
    } // Pane
  } // Component
  SplitView { 
    id: splitView
    anchors.fill: parent
  } // SplitView
} // Pane
// Usage

Pane {
  Component {
    id: redRect
    Rectangle { color: "Red" }
  } // Component
  Column { anchors.fill: parent
    Button {
      text: "add"
      onClicked: customSplitView.addItem("RED", redRect.createObject())
    } // Button 
    CustomSplitView { id: customSplitView }
  } // Column
} // Pane

Result: When "add" button clicked, adding item inside of the split view has "RED" text but green rectangle appears, not red.

It's not a size issue. (detailed resizing code has been omitted for code simplicity) Any advise will helps a lot, for what I missed, or other approaches.

CodePudding user response:

Whenever you want to dynamically create (and, possibly destroy) components, I would highly recommend using a model with a delegate. This will implementation pain that you're getting with createObject. With an appropriate structured ListModel parameter passing becomes trivial:

import QtQuick
import QtQuick.Controls
Page {
    header: Button {
        text: "add"
        onClicked: customSplitView.addItem("X", "lightsteelblue", 200, 300)
    }
    CustomSplitView {
        id: customSplitView
    }
}

// CustomSplitView.qml
import QtQuick
import QtQuick.Controls
Pane {
    anchors.fill: parent
    SplitView {
        anchors.fill: parent
        Repeater {
            model: ListModel {
                id: listModel
            }
            delegate: Rectangle {
                SplitView.preferredWidth: w
                SplitView.preferredHeight: h
                color: col
                Text {
                    anchors.centerIn: parent
                    text: txt
                }
            }
        }
    }
    function addItem(txt, col, w, h) {
         listModel.append( { txt, col, w, h } );
    }
    Component.onCompleted: {
        addItem( "RED", "red", 200, 200 );
        addItem( "GREEN", "green", 200, 200 );
        addItem( "ORANGE", "orange", 200, 200 );
    }
}

You can Try it Online!

CodePudding user response:

Thanks for insight of Stephen Quan, I could instantiate Component type as an argument of function.

// CustomSplitView.qml
import QtQuick 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.14

Pane {
  function addItem(text, component) {
    listModel.append( {text, component} )
  } // addItem
  SplitView { id: splitView
    anchors.fill: parent
    Repeater {
      model: ListModel { id: listModel } // ListModel
      delegate: Pane {
        property string _headerText: text /* input "text" */
        property var _component: component /* input "component" */
        ColumnLayout { anchors.fill: parent
          Label { text: _headerText } 
          Loader { Layout.fillWidth: true; Layout.fillHeight: true
            sourceComponent: _component
            Component.onCompleted: sourceComponent.createObject()
          } // Loader
        } // ColumnLayout
      } // Loader
    } // Repeater
  } // SplitView
} // Pane
// Usage

Window {  

  Component { id: rectComponent
    Rectangle { 
      color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
    } // Rectangle
  } // Component

  Component { id: labelComponent
    Label { 
      text: "Label "   Math.random()
    } // Label
  } // Component
  
  Pane { anchors.fill: parent
    ColumnLayout { anchors.fill: parent
      CustomSplitView { id: customSplitView
        Layout.fillWidth: true; Layout.fillHeight: true
        orientation: Qt.Horizontal
      } // customSplitView
      Button {
        text: "Add"
        onClicked: { 
          customSplitView.addItem(
            "Label", Math.random() < 0.5 ? rectComponent : labelComponent) 
        } // onClicked
      } // Button
    } // ColumnLayout
  } // Pane
} // Window

Now the "add" button generates random color of rectangle or random label randomly.

  • Related