QML can't anchor to item in layout - qt

Observe this quick example:
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
ApplicationWindow {
visible: true
width: 100
height: 100
Label {
text: "foobar"
anchors.bottom: row.top
anchors.left: label1.right
}
RowLayout {
id: row
anchors.bottom: parent.bottom
width: parent.width
Label {
id: label1
text: "hello1"
Layout.alignment: Qt.AlignLeft
}
Label {
id: label2
text: "hello2"
Layout.alignment: Qt.AlignRight
}
}
}
I have two items in row layout, and I want to anchor the third label to one of them. This is what i get:
I expect foobar to be more to the right, but it's not what I get.
Also with this any margins I set to the label will be ignored too.
I can anchor to window or to RowLayout and it would work nicely, but for some reason I can't anchor to items inside the layout. What's the reason and what's the appropriate solution for this?

When you compile the program you will get the error: Cannot anchor to an item that isn't a parent or sibling. Here's an answer, why you can't anchor. My solution in, that we will anchor to the left of row and then make margin with width of the label1 inside the row.
Here's a screenshot.
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
ApplicationWindow {
visible: true
width: 100
height: 100
Label {
color: "#b7087d"
text: "foobar"
anchors.bottom: row.top
anchors.left: row.left
anchors.leftMargin: label1.width
}
RowLayout {
id: row
anchors.bottom: parent.bottom
width: parent.width
Label {
id: label1
color: "#b22424"
text: "hello1"
Layout.alignment: Qt.AlignLeft
}
Label {
id: label2
color: "#1e62ce"
text: "hello2"
Layout.alignment: Qt.AlignRight
}
}
}

Related

How can I make my GroupBox Layouts scalable in QML?

I have the following problem. I created a Periodic table in QML that consists of GroupBoxes that contain a ColumnLayout in order to arrange the specific properties of each element. But as you can see in the pictures...
Window after starting
Window after downsizing
... the properties will not scale properly according to the size of the GroupBox. So when I scale down the size of the window, some text properties will just move out of its GroupBox and lay wherever they are not supposed to be. How can I fix this?
//PeriodicTable.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
import QtQuick.Layouts 1.15
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
GridView {
id: gridview
anchors.fill: parent
cellHeight: cellWidth * 1.5
cellWidth: parent.width / 18
delegate: PeriodicTableDelegate {
}
model: PeriodicTableModel {
}
}
}
}
//PeriodicTableModel.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ListModel {
id: elements
ListElement {
atomicWeight: "1.00794"
electronConfiguration: qsTr("1s")
elementName: qsTr("Hydrogen")
elementSign: qsTr("H")
ionizationEnergy: qsTr("13 5984")
ordinalNumber: qsTr("1")
unknownNumber: qsTr("S1/2")
}
} // I shortened this to just one element because yet it is the only one I have
// PeriodicTableDelegate.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
GroupBox {
property int cellHeight: GridView.view.cellHeight
property int cellWidth: GridView.view.cellWidth
height: cellHeight
width: cellWidth
ColumnLayout {
RowLayout {
Label {
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
font.bold: true
text: ordinalNumber
}
Label {
Layout.alignment: Qt.AlignRight
text: unknownNumber
}
}
Label {
Layout.alignment: Qt.AlignHCenter
font.bold: true
text: elementSign
}
Label {
Layout.alignment: Qt.AlignHCenter
text: elementName
}
Label {
Layout.alignment: Qt.AlignHCenter
text: atomicWeight
}
Label {
Layout.alignment: Qt.AlignHCenter
text: electronConfiguration
}
Label {
Layout.alignment: Qt.AlignHCenter
text: ionizationEnergy
}
}
}
a slightly contrived example:
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.0
Window {
height: 800
width: 600
visible: true
title: qsTr("cell test")
GridView {
id: grid
anchors.fill: parent
cellHeight: grid.height / 3
cellWidth: grid.width / 4
model: 12
delegate: Rectangle {
id: rect
width: grid.cellWidth
height: grid.cellHeight
color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
ColumnLayout {
id: layout
anchors.fill: parent
Repeater {
model: 5
Text {
id: txt
property int fsize: (layout.height + layout.width) / 30
Layout.fillWidth: true
text: "some text"
horizontalAlignment:Text.AlignHCenter
font.pointSize: fsize > 0 ? fsize : 16
}
}
}
}
}
}
The ColumnLayout in your GroupBox is missing an anchors.fill: parent.

Binding to a QML widget's rendered height

Let's say I have a text field and a button. I'd like to set the button's width and height to the text field's rendered height but it's not working.
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.10
Window {
id: window
visible: true
width: 640
height: 200
color: "#f0eded"
title: qsTr("Hello World")
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
TextField {
id: txtPassword
text: qsTr("Text Field")
font.pointSize: 22
}
Button {
id: btnSubmit
width: txtPassword.height
height: txtPassword.height
text: qsTr("»")
}
}
}
It looks like the button is ignoring the binding to the text field's height. My theory is that since this attribute isn't explicitly set, QML doesn't know which width/height to assign to the button.
What would be the proper way to take on the text field's actual rendered height?
If you use layout you should not use width or height, in case you want to obtain the same height you must use implicitWidth or implicitHeight, if you want the item to occupy the height of the row then you must use Layout.fillHeight: true. In the same way for the width.
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.10
Window {
id: window
visible: true
width: 640
height: 200
color: "#f0eded"
title: qsTr("Hello World")
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
TextField {
id: txtPassword
text: qsTr("Text Field")
font.pointSize: 22
}
Button {
id: btnSubmit
implicitHeight: txtPassword.implicitHeight // or Layout.fillHeight: true
implicitWidth: implicitHeight
text: qsTr("»")
}
}
}
Or instead of using RowLayout you could use a Row:
import QtQuick 2.0
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.3
import QtQuick.Window 2.10
Window {
id: window
visible: true
width: 640
height: 200
color: "#f0eded"
title: qsTr("Hello World")
Row {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: 5
TextField {
id: txtPassword
text: qsTr("Text Field")
font.pointSize: 22
}
Button {
id: btnSubmit
width: txtPassword.height
height: txtPassword.height
text: qsTr("»")
}
}
}

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
}
}
}

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"
}
}
}
}

Issue with toolbar layout, each tab is stacking on top of each other

I'm trying to get a tool bar working but the first 3 tab buttons keep writing on top of each other.
Each tab gets display on top of one another on the left hand side of the screen.
I would like each tab button to fill and take up its on unique space.
How do I get the toolbar to display 3 individual tabs that span horizontally across the screen at equal size?
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Material 2.1
import QtGraphicalEffects 1.0
import "../controls" as Controls
Page{
anchors.fill: parent
header: ToolBar{
Material.background: "green"
TabButton {
id: tab1
width: parent.width/3
text: qsTr("Asset")
Image{
source: "../assets/clipboard.png"
}
onClicked: qmlfile1 = "./asset.qml"
}
TabButton {
id:tab2
width: parent.width/3
text: qsTr("Issue")
Image{
source: "../assets/wrench.png"
}
onClicked: qmlfile1 = "./issue.qml"
}
TabButton {
width: parent.width/3
id: tab3
text: qsTr("Log")
Image{
source: "../assets/cogs.png"
}
onClicked: qmlfile1 = "./log.qml"
}
}
Rectangle{
id: loader1
Loader{
width: pageApp.width
source: qmlfile1
}
Component.onCompleted: {
console.log(loader1.height)
console.log(pageApp.height)
console.log(tabBarApp.height)
}
}
}
The solution was to add row layout and each tab button gets
Layout.fillHeight: true
Layout.fillWidth: true
which fills the tabs out to occupy all space it needs
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls.Material 2.1
import QtGraphicalEffects 1.0
import "../controls" as Controls
Page{
anchors.fill: parent
header: ToolBar{
Material.background: "green"
RowLayout {
anchors.fill: parent
TabButton {
id: tab1
width: parent.width/3
text: qsTr("Asset")
Layout.fillHeight: true
Layout.fillWidth: true
Image{
source: "../assets/clipboard.png"
Layout.alignment: Qt.AlignLeft
}
onClicked: qmlfile1 = "./asset.qml"
}
TabButton {
id:tab2
width: parent.width/3
Layout.fillHeight: true
Layout.fillWidth: true
text: qsTr("Issue")
Image{
source: "../assets/wrench.png"
Layout.alignment: Qt.AlignLeft
}
onClicked: qmlfile1 = "./issue.qml"
}
TabButton {
width: parent.width/3
Layout.fillHeight: true
Layout.fillWidth: true
id: tab3
text: qsTr("Log")
Image{
source: "../assets/cogs.png"
Layout.alignment: Qt.AlignLeft
}
onClicked: qmlfile1 = "./log.qml"
}
}
}
// Add a Loader to load different samples.
// The sample Qml files can be found in the Samples folder
Rectangle{
id: loader1
Loader{
width: pageApp.width
source: qmlfile1
}
Component.onCompleted: {
console.log(loader1.height)
console.log(pageApp.height)
console.log(tabBarApp.height)
}
}
}

Resources