How visual objects fit in the screen in QML? - qt

This is my QML code:
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.Layouts 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
GridLayout {
anchors.centerIn: parent
anchors.margins: 8
rowSpacing: 5
columnSpacing: 5
columns: 4
Repeater {
model: 12
Rectangle {
width: 100 / Screen.devicePixelRatio
height: 100 / Screen.devicePixelRatio
color: 'blue'
Text { anchors.centerIn: parent; text: index + 1; color: 'white' }
}
}
}
}
If I set model of Repeater is 12, the view is good like this:
But if I set model of Repeater is 36+ I get this view:
I want all rectangles to be sized and aligned according to the screen / window size. I want any rectangle doesn't overflow invisible space.
How can I do it?

f you want it to occupy all the vertical space available then you must make a calculation of the height of each rectangle:
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.Layouts 1.3
Window {
id: win
visible: true
width: 640
height: 480
title: qsTr("Hello World")
GridLayout {
id: gl
anchors.centerIn: parent
anchors.margins: 8
rowSpacing: 5
columnSpacing: 5
columns: 4
readonly property real heighItem : {
var rowCountEffective = Math.round(repeater.count/gl.columns)
var heightEffective = win.height-rowCountEffective*gl.rowSpacing - gl.anchors.topMargin -gl.anchors.bottomMargin
return heightEffective/(rowCountEffective * Screen.devicePixelRatio)
}
Repeater {
id: repeater
model: 50
Rectangle {
width: 100 / Screen.devicePixelRatio
height: gl.heighItem
color: 'blue'
Text { anchors.centerIn: parent; text: index+1; color: 'white' }
}
}
}
}

Related

QML Scroll Bar doesn't update when it is at the bottom and window height is resized

I have a custom scrollbar QML type that I am working on. The problem I'm having is that if the scroll bar is all the way at the bottom of the page and the height of the main application window is increased, the translated contents stay in place and the size of the scroll bar is not updated. After this window resize occurs, clicking on the scroll bar causes the content to snap to its proper place and the scroll bar to snap to its proper size. What changes might could be made to the code below so the position of the contents (red blocks) and scroll bar size update while the window height is changing? Not afterwards when the scroll bar has been clicked again. To see the issue just open the code below, scroll the blue scroll bar all the way to the bottom, increase the height of the main window (observing the scroll bar size and the content position), and then click on the scroll bar after the resize. Here is my code:
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
import QtQuick.Shapes 1.15
Window {
id: main_window
width: 640
height: 480
visible: true
title: qsTr("Hello World")
color: 'light blue'
// container
ColumnLayout {
id: my_column
anchors.centerIn: parent
width: main_window.width / 3
height: main_window.height / 3
spacing: 0
// contents
ColumnLayout {
id: repeater_element
Layout.fillWidth: true
Layout.fillHeight: false
spacing: 4
Repeater {
model: 7
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: false
Layout.preferredHeight: 75
Layout.alignment: Qt.AlignTop
color: 'red'
}
}
transform: Translate {
id: rect_translate
y: 0
}
}
}
// scroll bar type
Scroll_Bar {
x: 0
y: 0
height: parent.height
width: 20
container_element: my_column
content_element: repeater_element
translate_element: rect_translate
orientation: Qt.Vertical
}
// just a border for the container element
Shape {
ShapePath {
strokeWidth: 4
strokeColor: "black"
fillColor: Qt.rgba(.09, .05, .86, 0)
joinStyle: ShapePath.MiterJoin
startX: my_column.x
startY: my_column.y
PathLine {
relativeX: my_column.width
relativeY: 0
}
PathLine {
relativeX: 0
relativeY: my_column.height
}
PathLine {
relativeX: -my_column.width
relativeY: 0
}
PathLine {
relativeX: 0
relativeY: -my_column.height
}
}
}
}
Scroll_Bar.qml
import QtQuick 2.0
import QtQuick.Controls 2.5
ScrollBar {
property var container_element
property var content_element
property var translate_element
QtObject {
id: internal
property real vertical_size: container_element.height / content_element.height
property real horizontal_size: container_element.width / content_element.width
property real off_the_bottom: (content_element.height - container_element.height) + translate_element.y
}
id: scroll_bar_element
hoverEnabled: true
active: size
orientation: orientation
size: orientation === Qt.Vertical ? internal.vertical_size : internal.horizontal_size
padding: 0
contentItem: Rectangle {
id: ci
radius: 0
color: 'blue'
}
onSizeChanged: {
if(size > 1){
visible = false
}
else{
visible = true
}
}
onPositionChanged: {
if (orientation === Qt.Horizontal) {
translate_element.x = -scroll_bar_element.position * content_element.width
} else {
translate_element.y = -scroll_bar_element.position * content_element.height
}
}
Component.onCompleted: {
scroll_bar_element.onPositionChanged()
}
}
You can hardly write better scrollbar than the existing one, so I made the following code which does the same thing I saw in your example. ScrollBar can be the sibling of a flickable, so it won't take ownership and you can position it where you want. You can even make it rotated.
Is it something that solves your problem?
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
Window {
id: main_window
width: 640
height: 480
visible: true
title: qsTr("Hello World")
color: 'light blue'
Flickable {
id: flickable
anchors.centerIn: parent
width: main_window.width / 3
height: main_window.height / 3
contentWidth: repeater_element.width
contentHeight: repeater_element.height
ScrollBar.vertical: scrollBar
// container
ColumnLayout {
id: my_column
width: main_window.width / 3
height: main_window.height / 3
spacing: 0
// contents
ColumnLayout {
id: repeater_element
Layout.fillWidth: true
Layout.fillHeight: false
spacing: 4
Repeater {
model: 7
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: false
Layout.preferredHeight: 75
Layout.alignment: Qt.AlignTop
color: 'red'
}
}
transform: Translate {
id: rect_translate
y: 0
}
}
}
}
ScrollBar {
id: scrollBar
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
//try this for fun
//rotation: 5
contentItem: Rectangle {
implicitWidth: 20
implicitHeight: 20
color: "blue"
}
}
Rectangle {
color: "transparent"
border.width: 4
anchors.fill: flickable
}
}

QML RowLayout does not dynamically resize based on content

I have some experience with Qt Widgets, but only recently started to use QML.
The problem I face is that I'd like some layouts defined in QML to automatically adjust to fit their contents. This works, but not dynamically, i.e. if the content changes the layout does not adapt. With the old-style (non-QML) Layout/Widget approach, this happened automatically.
Here is an example (my code looks different and consists of different files, but I pasted this MWE together to demonstrate the problem):
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.2
Window {
id: root
visible: true
width: 640
height: 480
property var nbx: 3
Column {
RowLayout {
Repeater {
model: 3
Rectangle {
width: childrenRect.width
height: childrenRect.height
color: "green"
ColumnLayout {
Rectangle {
height: 10
}
RowLayout {
Repeater {
model: root.nbx
Rectangle {
width: 20
height: 20
color: "orange"
}
}
}
}
}
}
}
Button {
text: "5 boxes"
onClicked: root.nbx= 5;
}
Button {
text: "2 boxes"
onClicked: root.nbx = 2;
}
}
}
How can I achieve the same with QML?
You can make it work by setting the implicit size of the green Rectangle to the implicit size of the child ColumnLayout. I'm not exactly sure why, it seems the childrenRect properties are not propertly updated.
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.2
Window {
id: root
visible: true
width: 640
height: 480
property var nbx: 3
ColumnLayout {
RowLayout {
Repeater {
model: 3
Rectangle {
implicitHeight: col1.implicitHeight // <--- here is the change
implicitWidth: col1.implicitWidth
color: "green"
ColumnLayout {
id: col1
Rectangle {
height: 10
}
RowLayout {
Repeater {
model: root.nbx
Rectangle {
width: 20
height: 20
color: "orange"
}
}
}
}
}
}
}
Button {
text: "5 boxes"
onClicked: root.nbx= 5;
}
Button {
text: "2 boxes"
onClicked: root.nbx = 2;
}
}
}

Extra space at the bottom of Flow

I have a QML code like this:
MyItem.qml:
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Item {
id: root
width: parent.width
height: grid.height
Rectangle {
anchors.fill: root
color: "blue"
z: -1
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
main.qml:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.fill: parent
Button {
Layout.fillWidth: true
Layout.fillHeight: true
text: "hello"
}
MyItem {
Layout.fillWidth: true
}
}
}
If the Flow is wide enough for all three buttons to be at the same line (as with RowLayout) there is an extra empty space at the bottom of the Flow (approximately Button.height * 2). Looks like the Flow height is always calculated as the sum of all its element heights.
What is the logic behind this behavior? How to make the Flow fit its content height?
EDIT1: It is not Flow, but 'root' item has the wrong height.
EDIT2: Download the sample app
The problem with your code is that the root element the expressions:
anchors.fill: parent
height: grid.height
are competing, in the first expression you indicate that the dimensions of the root will take the size of the window and this implies the height but in the next expression you are indicating that the height will no longer be from the window but from the grid, so that generates an indefinite behavior. The only solution is to establish that the width of the root item is that of the window.
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Item {
id: root
height: grid.height
width: parent.width
Rectangle {
anchors.fill: root
color: "blue"
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
}
Update:
It seems that you do not know how they work (read https://doc.qt.io/qt-5/qml-qtquick-layouts-layout.html#details), by default the height that is taken is the implicitHeight.
Also if you use layout you should not set anchors in the items that are directly affected by the layouts, in your case the CommandsTab is affected by the Layout so you should not use width: parent.width, is unnecesary.
CommandsTab.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Item {
id: root
implicitHeight: grid.height
Rectangle {
anchors.fill: root
color: "blue"
z: -1
}
Flow {
id: grid
width: parent.width
spacing: 5
Button {
text: qsTr("Button 1")
}
Button {
text: qsTr("Button 2")
}
Button {
text: qsTr("Button 3")
}
}
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ColumnLayout {
anchors.fill: parent
Button {
Layout.fillWidth: true
Layout.fillHeight: true
text: "hello"
}
CommandsTab {
Layout.fillWidth: true
}
}
}

Creating a 6x4 grid in qml

I am trying to create a grid, consisting of squares. It is a 6X4 grid. The code which I am using to make the grid is below
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
import QtQuick.Window 2.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Mini Keno")
ColumnLayout {
spacing: 1
Item {
Row {
spacing: 1
Repeater {
id: mmm
model: 5
Rectangle {
id: imgl
width: 50
height: 50
color: "#4286f4"
property string src: ""
MouseArea {
anchors.fill: parent
onClicked: {
parent.color = "4286f4"
parent.color = "#2345F6"
}
}
}
}
}
}
Item {
Row {
spacing: 1
Repeater {
id: mm2
model: 5
Rectangle {
id: img2
width: 50
height: 50
color: "#4286f4"
property string src: ""
MouseArea {
anchors.fill: parent
onClicked: {
parent.color = "4286f4"
parent.color = "#2345F6"
}
}
}
}
}
}
}
}
This code is I am trying to create two lines of the grid, but the other line is not visible. So how to solve this problem of the grid where the squares are clickable. Also, how can I place the grid in the middle of the window?
height and width properties missing for Item, so Item has zero height, width. So the second row is overlapped with the first row.
Use anchors to make the layout in center, i.e anchors.centerIn: parent
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 1.4
import QtQuick.Window 2.3
Window {
visible: true
width: 640
height: 480
title: qsTr("Mini Keno")
ColumnLayout {
anchors.centerIn: parent // place layout in center
spacing: 1
height: 100
Item {
width: 300 // widht of item
height: 50 // height of item
Row {
spacing: 1
Repeater {
id: mmm
model: 5
Rectangle {
id: imgl
width: 50
height: 50
color: "#4286f4"
property string src: ""
MouseArea {
anchors.fill: parent
onClicked: {
parent.color = "4286f4"
parent.color = "#2345F6"
}
}
}
}
}
}
Item {
width: 300 // widht of item
height: 50 // height of item
Row {
spacing: 1
Repeater {
id: mm2
model: 5
Rectangle {
id: img2
width: 50
height: 50
color: "#4286f4"
property string src: ""
MouseArea {
anchors.fill: parent
onClicked: {
parent.color = "4286f4"
parent.color = "#2345F6"
}
}
}
}
}
}
}
}

Qt Quick layout changes on different events

When I execute my QML code, the output is:
When I minimize the window, It becomes like
and finally, when I again maximize the window it changes to
the GUI which I want to make looks like
![][5]
I am not getting what is the issue for all of the changes in GUI at different events. And this is the Qml code which I wrote
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
Window {
visible: true
width: 1080
height: 720
title: qsTr("Login")
GridLayout{
Rectangle{
id:one
Rectangle
{ id:two
color:"black";
width: 700
height:40
}
Image {
id: image
x: 470
y: 0
width: 54
height: 42
source: "qrc:/user.png"
}
Rectangle
{
id:three;
color:"#f47a42";
width: 200
height:40
anchors.left:two.right;
anchors.margins:940
Text {
id: user
text: qsTr("4200")
color:"white"
anchors.top: value.bottom
}
Text
{
id: value;
text: qsTr("User");
color:"yellow"
}}
}
}
Rectangle{
ColumnLayout{
width: 50
height: childrenRect.height+fillHeight;
}
color:"green"
}
}
So why this is happening and how can I solve this problem?
Output of the code below
Here is example of scalable window:
import QtQuick 2.11
import QtQuick.Window 2.11
import QtQuick.Layouts 1.11
Window {
visible: true
width: 800
height: 600
title: qsTr("Layout example")
ColumnLayout{
spacing: 0
anchors.fill: parent
Item {
id: titlebar
Layout.preferredHeight: 40
Layout.fillWidth: true
RowLayout {
anchors.fill: parent
spacing: 0
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "orange"
Text {
anchors.centerIn: parent
text: "Title"
}
}
Rectangle {
Layout.preferredWidth: 100
Layout.fillHeight: true
color: "lightgreen"
Text {
anchors.centerIn: parent
text: "Actions"
}
}
}
}
Rectangle {
id: content
Layout.fillHeight: true
Layout.fillWidth: true
color: "lightyellow"
Text {
anchors.centerIn: parent
text: "Content"
}
}
}
}

Resources