QML: set width based on left/right anchors of other Items - qt

How do I set the width of a QML item based on the values of other items' anchors.left and anchors.right? Here is an example of what I want to do:
Rectangle {
width: 400
height: 400
Rectangle {
width: parent.right - parent.left
height: parent.height
}
}
Obviously, this is only a simple example because I could just use width: parent.width, but that will not work in general. For instance, if the two anchors are on different items:
Rectangle {
width: 400
height: 400
Rectangle {
anchors.left: parent.left
width: other.left - parent.left
height: parent.height
}
Rectangle {
id: other
anchors.right: parent.right
width: 123
height: parent.height
}
}

I found a solution, though it is a bit messy. For the following code that does not work:
Rectangle {
width: 400
height: 400
Rectangle {
id: other1
anchors.left: parent.left
width: 43
height: parent.height
}
Rectangle {
anchors.left: other1.right
width: other2.left - other1.right
height: parent.height
}
Rectangle {
id: other2
anchors.right: parent.right
width: 123
height: parent.height
}
}
Replace other1.right with other1.x + other1.width and other2.left with other2.x, which gives us:
Rectangle {
width: 400
height: 400
Rectangle {
id: other1
anchors.left: parent.left
width: 43
height: parent.height
}
Rectangle {
anchors.left: other1.right
width: other2.x - (other1.x + other1.width)
height: parent.height
}
Rectangle {
id: other2
anchors.right: parent.right
width: 123
height: parent.height
}
}

You are adding unnecessary complexity to a simple problem.
As long as you want to anchor the item to its siblings or direct parent, you don't need to manually calculate the width of your item.
See Positioning with Anchors.
Just anchor the left and right values:
Rectangle {
width: 400
height: 400
Rectangle {
id: other1
anchors.left: parent.left
width: 43
height: parent.height
}
Rectangle {
anchors.left: other1.right
anchors.right: other2.left
// width: other2.x - (other1.x + other1.width) // absolutely not necessary
height: parent.height
}
Rectangle {
id: other2
anchors.right: parent.right
width: 123
height: parent.height
}
}

Related

QT QML what is the best approach for static layout

I need a complete static layout with fixed positions and sizes like this.
Do I need a grid or column layout with relative positioning or can I work without any layout (only with x and y positioning and fixed sizes)?
You could use positioners with Rectangles that have the static size set to them like this.
Column {
Rectangle { width: 100; height: 10; color: "#4472c4" }
Row {
Rectangle { width: 10; height: 60; color: "#8497b0" }
Rectangle { width: 80; height: 60; color: "#a6a6a6" }
Rectangle { width: 10; height: 60; color: "#333f50" }
}
Rectangle { width: 100; height: 10; color: "#d6dce5" }
}
You could also use x and y positioning without positioners.
Rectangle { width: 100; height: 10; color: "#4472c4" }
Rectangle { y: 10; width: 10; height: 60; color: "#8497b0" }
Rectangle { x: 10; y: 10; width: 80; height: 60; color: "#a6a6a6" }
Rectangle { x: 90; y: 10; width: 10; height: 60; color: "#333f50" }
Rectangle { y: 70; width: 100; height: 10; color: "#d6dce5" }
Or anchors
Rectangle { id: topRect; width: 100; height: 10; color: "#4472c4" }
Rectangle {
id: leftRect
anchors.top: topRect.bottom
anchors.left: parent.left
width: 10; height: 60; color: "#8497b0"
}
Rectangle {
id: centerRect
anchors.top: topRect.bottom
anchors.left: leftRect.right
x: 10; y: 10; width: 80; height: 60; color: "#a6a6a6"
}
Rectangle {
id: rightRect
anchors.top: topRect.bottom
anchors.left: centerRect.right
x: 90; y: 10; width: 10; height: 60; color: "#333f50"
}
Rectangle {
id: bottomRect
anchors.top: centerRect.bottom
y: 70; width: 100; height: 10; color: "#d6dce5"
}
Or you could use layouts, but I prefer positioners over layouts.
Here's a solution using Layouts. The advantage is, whilst I gave the dimensions 100x80 container, the outer Rectangles needed minimal 10 pixel sizing information, whilst the inner most Rectangle didn't need any sizing, since, I made use of Layout.fillWidth: true and Layout.fillHeight: true as appropriate.
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
ColumnLayout {
anchors.centerIn: parent
width: 100
height: 80
spacing: 0
Rectangle {
id: r1
Layout.fillWidth: true
Layout.preferredHeight: 10
color: "blue"
}
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
Rectangle {
id: r2
Layout.preferredWidth: 10
Layout.fillHeight: true
color: "navy"
}
Rectangle {
id: r5
Layout.fillWidth: true
Layout.fillHeight: true
color: "grey"
}
Rectangle {
id: r4
Layout.preferredWidth: 10
Layout.fillHeight: true
color: "darkblue"
}
}
Rectangle {
id: r3
Layout.fillWidth: true
Layout.preferredHeight: 10
color: "lightsteelblue"
}
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
text: `
R1: ${r1.width} x ${r1.height}
R2: ${r2.width} x ${r2.height}
R3: ${r3.width} x ${r3.height}
R4: ${r4.width} x ${r4.height}
R5: ${r5.width} x ${r5.height}
`
}
}
You can Try it Online!

Get ProgressBar to fill Rectangle qml

I have a rectangle where I want to have a border around the Rectangle and the ProgressBar fit inside this rectangle while still being able to see the border.
Using qmlonline tool below I am able to create the Rectangle with ProgressBar, but the ProgressBar covers the whole Rectangle
import QtQuick 2.7
import QtQuick.Controls 2.3
Item {
width: 500
height: 250
Rectangle {
color: "black"
anchors.fill: parent
Rectangle {
id: rect1
width: 250
height: 50
border.width: 1
border.color: "white"
color: "transparent"
ProgressBar {
id: pBar
value: 0.5
background: Rectangle {
width: rect1.width
height: rect1.height
color: "gray"
}
contentItem: Item {
Rectangle {
width: pBar.visualPosition * rect1.width
height: rect1.height
color: "green"
}
}
}
}
}
}
I've tried modifying the background: and contentItem: components to get this to happen, but it doesn't work quite right.
Below is my attempt
import QtQuick 2.7
import QtQuick.Controls 2.3
Item {
width: 500
height: 250
Rectangle {
color: "black"
anchors.fill: parent
Rectangle {
id: rect1
width: 250
height: 50
border.width: 1
border.color: "white"
color: "transparent"
ProgressBar {
id: pBar
value: 1
background: Rectangle {
width: rect1.width
height: rect1.height * 0.925
anchors.verticalCenter: parent.verticalCenter
color: "gray"
}
contentItem: Item {
implicitWidth: rect1.width
implicitHeight: rect1.height
Rectangle {
width: pBar.visualPosition * rect1.width
height: rect1.height * 0.925
anchors.verticalCenter: parent.verticalCenter
color: "green"
}
}
}
}
}
}
When the progress is at 100% you can see that on the left and right side you cannot see rect1's border, but you can see it on the top and bottom.
use anchor instead of "width and height"
import QtQuick 2.7
import QtQuick.Controls 2.3
Item {
width: 500
height: 250
Rectangle {
color: "black"
anchors.fill: parent
Rectangle {
id: rect1
width: 250
height: 50
border.width: 1
border.color: "white"
color: "transparent"
ProgressBar {
id: pBar
value: 0.9
anchors.fill: parent
anchors.margins:1
background: Rectangle {
anchors.fill:parent
color: "gray"
}
contentItem: Item {
Rectangle {
width: pBar.visualPosition * parent.width
height: parent.height
color: "green"
}
}
}
}
}
}

How to set background color to Row?

I am trying to give Background color to Row element in my app.
So far I archived this with rectangle but it is messing up Images in MouseArea
Here is my code:-
import QtQuick.Controls 2.4
import QtQuick 2.11
ApplicationWindow {
id:rootAppWin
width:640
height:480
visible: true
StackView {
id: rooAppStack
anchors.bottomMargin: 50
anchors{
fill:parent
}
}
//Bottom Buttons
Row{
Rectangle {
color: "#19d4d4d4"
anchors.fill:parent
}
id:rootNavButtons
anchors{
top: rooAppStack.bottom
right: parent.right
bottom: parent.bottom
left: parent.left
topMargin: 5
}
MouseArea {
id:marootback
width: parent.width/2
height: parent.height
Image {
id: marootbackimg
fillMode: Image.PreserveAspectFit
source: "qrc:/img/sideswipe.svg"
anchors.fill:parent
}
}
MouseArea {
id:maroothome
width: parent.width/2
height: parent.height
Image {
id: maroothomeimg
fillMode: Image.PreserveAspectFit
source: "qrc:/img/tent.svg"
anchors.fill:parent
}
}
}
}
It messes up the images:-
Without rectangle it works great but I can't set background color . What should I do ?
Put Row in Rectangle
Rectangle {
color: "#19d4d4d4"
anchors{
top: rooAppStack.bottom
right: parent.right
bottom: parent.bottom
left: parent.left
topMargin: 5
}
Row{
anchors.fill:parent
id:rootNavButtons
MouseArea {
id:marootback
width: parent.width/2
height: parent.height
Image {
id: marootbackimg
fillMode: Image.PreserveAspectFit
source: "qrc:/img/sideswipe.svg"
anchors.fill:parent
}
}
MouseArea {
id:maroothome
width: parent.width/2
height: parent.height
Image {
id: maroothomeimg
fillMode: Image.PreserveAspectFit
source: "qrc:/img/tent.svg"
anchors.fill:parent
}
}
}
}

How to make a particular area of qml view transparent

There is a qml file like this:
Item {
width: 800
height: 600
Image {
id: background
width: 800
height: 600
source: "qrc:/resorces/background.png"
}
Rectangle {
id: transframe
x: 500
y: 200
width: 200
height: 100
}
}
How to make the area of transframe transparent, then I can see the graphic under background.
The OpacityMask is what you are looking for.
Example:
Rectangle {
width: 800; height: 600
color: 'red'
Image {
id: background
width: 800; height: 600
source: "qrc:/resorces/background.png"
visible: false
}
Item {
id: transframe
width: 800; height: 600
visible: false
Rectangle {
x: 500; y: 200; width: 200; height: 100
}
}
OpacityMask { // don't forget to import QtGraphicalEffects
anchors.fill: background
source: background
maskSource: transframe
invert: true
}
}
Item {
width: 800
height: 600
Image {
id: background
width: 800
height: 600
source: "qrc:/resorces/background.png"
}
Rectangle {
id: transframe
x: 500
y: 200
width: 200
height: 100
color:"transparent"
}
}

Flick a column positioner

How do we make a Positioner for example a Column flickable.
For example :
import QtQuick 2.0
Item {
width: 200
height: 200
Column {
spacing: 2
Rectangle { color: "red"; width: 50; height: 50 }
Rectangle { color: "green"; width: 20; height: 50 }
Rectangle { color: "blue"; width: 50; height: 20 }
}
}
You need to at least set the following properties of the Flickable:
width and height (and/or anchors)
contentWidth and contentHeight
The following code should do the trick:
import QtQuick 2.0
Item {
width: 200
height: 200
Flickable {
//anchors.fill: parent
width: 100
height: 50
contentWidth: col.width // you can use whatever you want, this is just an example
contentHeight: col.height // same here
Column {
id: col
spacing: 2
Rectangle { color: "red"; width: 50; height: 50 }
Rectangle { color: "green"; width: 20; height: 50 }
Rectangle { color: "blue"; width: 50; height: 20 }
}
}
}

Resources