Search code examples
qtlayoutqmlalignmentanchor

How to use own objects in ColumnLayout in QML?


I would like to produce a table where in every Row is a Text() and a ComboBox(). I want the comboboxes are aligned right and also the left side of the text labels something like that:

enter image description here

I have the main qml:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12



Window {
    id: wind
    width: 640
    height: 480
    visible: true
    title: qsTr("Public Transport Searcher")
    property string oz: "Odjezdová zastávka"
    property string pz: "Příjezdová zastávka"
    property string co: "Čas odjezdu"




    Rectangle{
        id: rect
        x: wind.width/16
         implicitHeight: parent.height/3*2
         implicitWidth: wind.width/8*7
         anchors.right: parent.right
         anchors.left: parent.left
         anchors.margins: 20
        radius: 5


        color: "lightblue"

   ColumnLayout{
        id: cl
        spacing: 30
        width: parent.width
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.margins: 20
        anchors.fill: parent


    Row{
        id: r1
        Layout.alignment: Qt.AlignTop
        //Layout.alignment: Qt.AlignTop
        Layout.margins: 15

        Text{
            id: r1t1
            text: "Vyhledávač jízdních řádů"
            font.pointSize: 16
            font.bold: true
        }
    }

     Line{

         id: r2
         tt2: oz
         Layout.alignment: Qt.AlignLeft
         //anchors.top: r1.bottom
     }

     Line{

         id: r3
         tt2: pz
         Layout.alignment: Qt.AlignLeft
     }

     Line{

         id: r4
         tt2: co
         Layout.alignment: Qt.AlignLeft
     }


        }
    }


   }

And a separate Line.qml item:

import QtQuick 2.15
import QtQuick.Controls 2.12


Item {

     property string tt2: "v"

        Text{
            id: txt
            text: tt2
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: parent.left
        }
        ComboBox{
            id: cb
            anchors.verticalCenter: parent.verticalCenter
            //anchors.fill: parent
            anchors.left: txt.right
        }

}

Now it runs but the all Rows are overwritting in the top left corner. I know that I could use the GridLayout but I want to take advantage from the own objects for one row (in case I have much such rows) to avoid copy paste technic and initialise every object of the row separate. Could you show me please how to do that in an elagant way?


Solution

  • The problem is that your Line items do not have any implicit size which the ColumnLayout can read from. That is, the Line's base is just an Item whose default implicitHeight and implicitWidth are both 0 - so the ColumnLayout renders them improperly. You have several options.

    One option is to add implicitHeight/implicitWidth (or Layout.preferredWidth/Layout.preferredHeight) to your Line's Item:

    import QtQuick 2.12
    import QtQuick.Controls 2.12
    
    Item {
        implicitHeight: 30
        implicitWidth: parent.width
        property string tt2: "v"
    
        Text{
            id: txt
            text: tt2
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: parent.left
        }
    
        ComboBox{
            id: cb
            anchors.verticalCenter: parent.verticalCenter
            //anchors.fill: parent
            anchors.left: txt.right
        }
    }
    

    A different way of accomplishing this would be to change the base of the Line to a RowLayout (and remove the interior anchors which would conflict):

    import QtQuick 2.12
    import QtQuick.Controls 2.12
    import QtQuick.Layouts 1.12
    
    RowLayout {
        property string tt2: "v"
    
        Text {
            id: txt
            text: tt2
            Layout.preferredWidth: 200 // to align ComboBoxes, all text must have same width
            // Layout.fillWidth: true // a different option for aligning ComboBoxes
        }
            
        ComboBox {
            id: cb
        }
    }