lnk
lnk

Reputation: 603

GridLayout items size is not equal to each other

I have got Qt class which is subclass of QQuickImageProvider here is requestPixmap function realization:

QPixmap MyImageProvider::requestPixmap(const QString &id, QSize *size, const QSize       
    &requestedSize){
    int width = 100;
        int height = 50;

        if (size)
            *size = QSize(width, height);
        QPixmap pixmap(requestedSize.width() > 0 ? requestedSize.width() : width,
                       requestedSize.height() > 0 ? requestedSize.height() : height);
        pixmap.fill(QColor(id).rgba());

        return pixmap;
 }

In qml I have GridLayout which items is came from image provider. By clicking buttons I can show 1, 2 or 4 items. Here is qml file:

 import QtQuick 2.3
 import QtQuick.Controls 1.2
 import QtQuick.Layouts 1.1
 import QtQuick.Controls.Styles 1.1
 import QtQuick.Window 2.2

 Window{
     id: root
     title: "settings"
     modality: Qt.ApplicationModal
     flags: Qt.Dialog
     minimumHeight: 700
     minimumWidth: 700
     maximumHeight: 700
     maximumWidth: 700
     ColumnLayout{
          id: columnLayout
          anchors.fill: parent
          RowLayout{
              ExclusiveGroup{id: exgroup}
              Button{
                  text: "1x1"
                  checkable: true
                  checked: true
                  Layout.minimumWidth: 100
                  Layout.minimumHeight: 100
                  exclusiveGroup: exgroup
                  onCheckedChanged: {
                      if(checked===true){
                      grid.columns=1
                      grid.rows=1
                      im1.visible = true
                      im2.visible = false
                      im3.visible = false
                      im4.visible = false
                      im1.source = "image://plotPixmap/yellow"
                }
            }
            }

        Button{
            text: "1x2"
            checkable: true
            checked: false
            Layout.minimumWidth: 100
            Layout.minimumHeight: 100
            exclusiveGroup: exgroup
            onCheckedChanged: {
                if(checked===true){
                    grid.columns=1
                    grid.rows=2
                    im1.visible = true
                    im2.visible = true
                    im3.visible = false
                    im4.visible = false
                    im1.source = "image://plotPixmap/red"
                    im2.source = "image://plotPixmap/black"


                }
            }
        }
        Button{
            text: "2x1"
            checkable: true
            checked: false
            Layout.minimumWidth: 100
            Layout.minimumHeight: 100
            exclusiveGroup: exgroup
            onCheckedChanged: {
                if(checked===true){
                    grid.columns=2
                    grid.rows=1
                    im1.visible = true
                    im2.visible = true
                    im3.visible = false
                    im4.visible = false
                    im1.source = "image://plotPixmap/blue"
                    im2.source = "image://plotPixmap/green"

                }
            }
        }
        Button{
            text: "2x2"
            checkable: true
            checked: false
            Layout.minimumWidth: 100
            Layout.minimumHeight: 100
            exclusiveGroup: exgroup
            onCheckedChanged: {
                if(checked===true){
                    grid.columns=2
                    grid.rows=2
                    im1.visible = true
                    im2.visible = true
                    im3.visible = true
                    im4.visible = true
                    im1.source = "image://plotPixmap/blue"
                    im2.source = "image://plotPixmap/green"
                    im3.source = "image://plotPixmap/black"
                    im4.source = "image://plotPixmap/red"
                }
            }
        }
    }
    GridLayout {
        id: grid
        Layout.fillHeight: true
        Layout.fillWidth: true
        Image{
            id: im1
            Layout.fillHeight: true
            Layout.fillWidth: true
            sourceSize.height: height
            sourceSize.width: width
            Layout.rowSpan: 1
            Layout.columnSpan: 1
        }
        Image{
            id: im2
            Layout.fillHeight: true
            Layout.fillWidth: true
            sourceSize.height: height
            sourceSize.width: width
            Layout.rowSpan: 1
            Layout.columnSpan: 1
        }
        Image{
            id: im3
            Layout.fillHeight: true
            Layout.fillWidth: true
            sourceSize.height: height
            sourceSize.width: width
            Layout.rowSpan: 1
            Layout.columnSpan: 1
        }
        Image{
            id: im4
            Layout.fillHeight: true
            Layout.fillWidth: true
            sourceSize.height: height
            sourceSize.width: width
            Layout.rowSpan: 1
            Layout.columnSpan: 1
        }
    }
}
}

In c++ main:

engine->addImageProvider(QLatin1String("plotPixmap"), new MyImageProvider());

Everything works but when I press buttons several times size of bottom images became smaller and smaller. How to fix size o images? I want all images to be the same size and they shuld fill all space under buttons.

Upvotes: 2

Views: 5562

Answers (1)

BaCaRoZzo
BaCaRoZzo

Reputation: 7682

That's the result of the interactions between the different fillHeight/fillwidth set. As stated in the documentation:

The fillWidth and fillHeight properties can either be true or false. If it is false, the item's size will be fixed to its preferred size. Otherwise, it will grow or shrink between its minimum and maximum size as the layout is resized.

In this case, the minimum width is not set for the four images. Hence, as the GridLayout structure changes, according to the pressed button, the constraints are recalculated and in certain patterns (e.g. 2x1 -> 1x1 -> 2x1) the recalculated widths/heights gives more space to the first images (according to the flow). To fix the problem you should ensure that the minimum width/height are set on each image, i.e. Layout.minimumWidth and Layout.minimumHeight attached properties has the correct values.

Directly set such values in the code results in binding loops. Again from the documentation:

Note: It is not recommended to have bindings to the x, y, width, or height properties of items in a layout, since this would conflict with the goal of the Layout, and also cause binding loops.

To avoid the problem, the GridLayout is embeded in an Item which fills the ColumnLayout in place of the GridLayout itself. Size constraints are then safely applied to the images. Here is the final code:

import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2

Window{
    id: root
    title: "settings"
    modality: Qt.ApplicationModal
    flags: Qt.Dialog
    minimumHeight: 700
    minimumWidth: 700
    maximumHeight: 700
    maximumWidth: 700
    visible:  true

    ColumnLayout{
        id: columnLayout
        anchors.fill: parent
        RowLayout{
            ExclusiveGroup{id: exgroup}
            Button{
                text: "1x1"
                checkable: true
                checked: true
                Layout.minimumWidth: 100
                Layout.minimumHeight: 100
                exclusiveGroup: exgroup
                onCheckedChanged: {
                    if(checked){
                        grid.columns = grid.rows = 1
                        im1.visible = true
                        im2.visible = im3.visible = im4.visible = false
                        im1.source = "image://plotPixmap/yellow"
                    }
                }
            }

            Button{
                text: "1x2"
                checkable: true
                checked: false
                Layout.minimumWidth: 100
                Layout.minimumHeight: 100
                exclusiveGroup: exgroup
                onCheckedChanged: {
                    if(checked){
                        grid.columns = 1
                        grid.rows = 2
                        im1.visible = im2.visible = true
                        im3.visible = im4.visible = false
                        im1.source = "image://plotPixmap/red"
                        im2.source = "image://plotPixmap/black"
                    }
                }
            }
            Button{
                text: "2x1"
                checkable: true
                checked: false
                Layout.minimumWidth: 100
                Layout.minimumHeight: 100
                exclusiveGroup: exgroup
                onCheckedChanged: {
                    if(checked){
                        grid.columns = 2
                        grid.rows = 1
                        im1.visible = im2.visible = true
                        im3.visible = im4.visible = false
                        im1.source = "image://plotPixmap/blue"
                        im2.source = "image://plotPixmap/green"

                    }
                }
            }
            Button{
                text: "2x2"
                checkable: true
                checked: false
                Layout.minimumWidth: 100
                Layout.minimumHeight: 100
                exclusiveGroup: exgroup
                onCheckedChanged: {
                    if(checked){
                        grid.columns = grid.rows = 2
                        im1.visible = im2.visible = im3.visible = im4.visible = true
                        im1.source = "image://plotPixmap/blue"
                        im2.source = "image://plotPixmap/green"
                        im3.source = "image://plotPixmap/black"
                        im4.source = "image://plotPixmap/red"
                    }
                }
            }
        }
        Item {      // layout ensure to fill the available space
            Layout.fillHeight: true
            Layout.fillWidth: true

            GridLayout {
                id: grid
                anchors.fill: parent     // anchor to the available space

                Image{
                    id: im1
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    Layout.minimumWidth: grid.width / 2      // constraint to the min width
                    Layout.minimumHeight:  grid.height / 2   // constraint to the min height
                    Layout.rowSpan: 1
                    Layout.columnSpan: 1
                }
                Image{
                    id: im2
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    Layout.minimumWidth: grid.width / 2     // constraint to the min width
                    Layout.minimumHeight:  grid.height / 2  // constraint to the min height
                    Layout.rowSpan: 1
                    Layout.columnSpan: 1
                }
                Image{
                    id: im3
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    Layout.minimumWidth: grid.width / 2     // constraint to the min width
                    Layout.minimumHeight:  grid.height / 2  // constraint to the min height
                    Layout.rowSpan: 1
                    Layout.columnSpan: 1
                }
                Image{
                    id: im4
                    Layout.fillHeight: true
                    Layout.fillWidth: true
                    Layout.minimumWidth: grid.width / 2     // constraint to the min width
                    Layout.minimumHeight:  grid.height / 2  // constraint to the min height
                    Layout.rowSpan: 1
                    Layout.columnSpan: 1
                }
            }
        }
    }
}

Upvotes: 6

Related Questions