How do I create a scaleable GridLayout in QML?

62 Views Asked by At

I am currently trying to create an application that includes a Periodic table. I want to to display this as a GridLayout where each Element is represented as a GroupBox inside the Layout. The problem I am facing is that the GridLayout wont scale properly with the window that it is positioned in. It opens up as follows:

GridLayout on first start

I can also scale up the window like this:

GridLayout after upsizing the window

or donwscale it like the following:

GridLayout after downsizing the window

As you can see, the GridLayout doesnt seem to scale with the window size. Instead it seems to have a fixed size (Some elements are cut off from the beginning, if I scale down the window the elements are also being cut off)

Here is my code:

Item {
    id: root
    Button {
        id: button
        checkable: true
        text: qsTr("Show")

        onClicked: window.show()
    }
    Window {
        id: window
        Material.accent: parent.Material.accent
        Material.background: parent.Material.background
        Material.foreground: parent.Material.foreground
        Material.primary: parent.Material.primary
        Material.theme: parent.Material.theme
        color: Material.background
        height: parent.height
        title: qsTr("Periodic table")
        width: parent.width

        GridLayout {
            id: grid
            columns: 18

            PeriodicTableElement {
                Layout.fillHeight: true
                Layout.fillWidth: true
                atomicWeight: qsTr("1.00794")
                electronConfiguration: qsTr("1s")
                elementName: qsTr("Hydrogen")
                elementSign: qsTr("H")
                ionizationEnergy: qsTr("13 5984")
                ordinalNumber: qsTr("1")
                unknownNumber: qsTr("S1/2")
            }
            Repeater {
                model: 16

                GroupBox {
                    background: Item {
                    }
                }
            }
            Repeater {
                model: 3

                PeriodicTableElement {
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    atomicWeight: qsTr("1.00794")
                    electronConfiguration: qsTr("1s")
                    elementName: qsTr("Hydrogen")
                    elementSign: qsTr("H")
                    ionizationEnergy: qsTr("13 5984")
                    ordinalNumber: qsTr("1")
                    unknownNumber: qsTr("S1/2")
                }
            }
            Repeater {
                model: 10

                GroupBox {
                    background: Item {
                    }
                }
            }
            Repeater {
                model: 6

                PeriodicTableElement {
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    atomicWeight: qsTr("1.00794")
                    electronConfiguration: qsTr("1s")
                    elementName: qsTr("Hydrogen")
                    elementSign: qsTr("H")
                    ionizationEnergy: qsTr("13 5984")
                    ordinalNumber: qsTr("1")
                    unknownNumber: qsTr("S1/2")
                }
            }
            Repeater {
                model: 100

                PeriodicTableElement {
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    atomicWeight: qsTr("1.00794")
                    electronConfiguration: qsTr("1s")
                    elementName: qsTr("Hydrogen")
                    elementSign: qsTr("H")
                    ionizationEnergy: qsTr("13 5984")
                    ordinalNumber: qsTr("1")
                    unknownNumber: qsTr("S1/2")
                }
            }
        }
    }
}

I already tried using anchors.fill: window for the GridLayout but it didnt seem to have any effect.

So do I make this GridLayout scale with the window item which is his parent?

Thanks in advance for any helpful comment.

1

There are 1 best solutions below

0
On BEST ANSWER

Have you considered GridView instead? This will have the following advantages:

  • Provide the dimension of each delegate via cellWidth and cellHeight
  • Provide a ListModel that helps us render the periodic table

Here's a mock implementation of the first two lines of the periodic table using this approach:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    GridView {
        id: grid
        anchors.fill: parent
        cellWidth: parent.width / 18
        cellHeight: cellWidth * 2
        model: ElementsModel { }
        delegate: ElementDelegate { }
    }
}

// ElementsModel.qml
import QtQuick
import QtQuick.Controls
ListModel {
    id: elems
    ListElement { at: 1; sy: "H"; na: "Hydrogen"; co: "#ccf" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 2; sy: "He"; na: "Helium"; co: "pink" }
    ListElement { at: 3; sy: "Li"; na: "Lithum"; co: "#cff" }
    ListElement { at: 4; sy: "Be"; na: "Beryllium"; co: "#fcc" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 0; sy: ""; na: ""; co: "" }
    ListElement { at: 5; sy: "B"; na: "Boron"; co: "#ffe" }
    ListElement { at: 6; sy: "C"; na: "Carbon"; co: "#ccf" }
    ListElement { at: 7; sy: "N"; na: "Nitrogen"; co: "#ccf" }
    ListElement { at: 8; sy: "O"; na: "Oxygen"; co: "#ccf" }
    ListElement { at: 9; sy: "F"; na: "Flourine"; co: "#ccf" }
    ListElement { at: 10; sy: "Ne"; na: "Neon"; co: "pink" }
}

// ElementDelegate.qml
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Rectangle {
    property int cellWidth: GridView.view.cellWidth
    property int cellHeight: GridView.view.cellHeight
    width: cellWidth
    height: cellHeight
    color: co ? co : "#eee"
    Text {
        anchors.centerIn: parent
        text: sy
        font.pixelSize: cellHeight / 4
    }
    Text {
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        text: na
        font.pixelSize: tm.scaledPixelSize
    }
    Text {
        text: at
        visible: at
        font.pixelSize: cellWidth / 5
    }
    TextMetrics {
        id: tm
        text: na
        font.pixelSize: 10
        property real scaledPixelSize: cellWidth / tm.width * font.pixelSize * 0.9
    }
}

You can Try it Online!