Margin isn't working in qml - qt

I am making UI for a game. When I tried to put margin for the image tab.png
It doesn't reflect any changes to it. It stays where it was before. I also tried to solve this problem by adding the margins through the Layout and by adding it outside the rectangle and row layout but nothing happened.
Also when I am adding margin to the bottom to the user.png to shift it a bit upward, it isn't shifting. So please help me out to solve this. I want to position the tab.png as this layout
The second circle is where I want to place the tab.png. The output of the code
Window {
visible: true
width: 800
height: 600
title: qsTr("Main screen")
ColumnLayout{
spacing: 0
anchors.fill: parent
Item {
id: titlebar
Layout.preferredHeight: 60
Layout.fillWidth: true
RowLayout {
anchors.fill: parent
spacing: 0
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "black"
Image {
source: "qrc:/img/tab.png"
anchors.leftMargin: undefined
Layout.leftMargin: 20
}
}
Rectangle {
Layout.preferredWidth: 100
Layout.fillHeight: true
color: "#f46b42"
/*Text {
anchors.centerIn: parent
text: "Actions"
}*/
Image{
id:image_user
source: "qrc:/img/user.png"
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset:
anchors.left=parent.left
anchors.leftMargin: 10
clip: true
}
Item{
id:text_content
anchors.centerIn: parent
anchors.bottomMargin: 20
Text{
id:text_user
text: "User"
anchors.bottom:text_value.top
anchors.bottomMargin: 4
}
Text{
id:text_value
text:"$ 2000"
color:"yellow"
}}
}
}
}
Rectangle {
id: content
Layout.fillHeight: true
Layout.fillWidth: true
color: "lightyellow"
Text {
anchors.centerIn: parent
}
Column{
spacing: 1;
Repeater{
id:mmm
model: 5
Rectangle{
id:imgl
width: 100
height: 100
color: "#4286f4"
property string src: ""
MouseArea{
anchors.fill:parent
onClicked: {
parent.color="";
}
}
Image {
id: imgx
source: parent.src;
anchors.verticalCenter: parent.verticalCenter
}
onParentChanged: {
mmm.itemAt(0).src="qrc:/img/5by90.png";
mmm.itemAt(1).src="qrc:/img/6by42.png";
mmm.itemAt(2).src="qrc:/img/12by24.png";
mmm.itemAt(3).src="qrc:/img/fortune.png";
mmm.itemAt(4).src="qrc:/img/mini-roulette.png";
}
}
}
}
}
}
}

Layouts only affect your direct children, not the children of the children., so Layout.leftMargin: 20 will not affect Image as you see in this case.
The solution is really simple, it establishes the property x: 20 since the position of item is with respect to the parent's topleft position
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "black"
Image {
x:20
source: "qrc:/img/tab.png"
}
}

Inside Rectangle, for child elements, you need to use anchors.margin, whereas for Layouts child element can use Layout.margin.You need to use anchors.leftMargin: as Parent is Rectangle, Layout.margin will not have any effect.
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "black"
Image {
source: "qrc:/img/tab.png"
anchors.leftMargin: 20
}
}

Related

Transition problem in StackView which is displayed on Dialog

Well, I've run into a problem with my StackView in Dialog. You can see it in this example.
Maybe I need to rewrite the animation?
Here is my code:
Dialog {
id: settingDialog
anchors.centerIn: parent
width: 350
height: parent.height / 1.1
closePolicy: Dialog.NoAutoClose
background: Rectangle {
color: "darkgrey"
border.color: "cyan"
radius: 5
}
ColumnLayout {
anchors.fill: parent
spacing: 5
ToolBar {
Layout.fillWidth: true
Layout.minimumHeight: 60
background: Rectangle { color: "transparent" }
RowLayout {
anchors.fill: parent
ToolButton {
id: tbBack
enabled: true
Layout.alignment: Qt.AlignHCenter
Layout.minimumWidth: 30
Layout.leftMargin: 10
background: Rectangle {
color: tbBack.hovered ? "darkcyan" : "transparent"
radius: parent.width
}
onClicked: stackViewSettings.pop()
}
Item { Layout.fillWidth: true }
ToolButton {
id: tbClose
Layout.alignment: Qt.AlignHCenter
Layout.minimumWidth: 30
Layout.rightMargin: 10
icon.source: "ADD YOUR ICO"
background: Rectangle {
color: tbClose.hovered ? "cyan" : "transparent"
radius: parent.width
}
onClicked: {
settingDialog.close()
stackViewSettings.pop()
}
}
}
}
//
StackView {
id: stackViewSettings
Layout.fillWidth: true
Layout.fillHeight: true
initialItem: Page {
background: Rectangle { color: noColor }
ColumnLayout {
anchors.fill: parent
spacing: 0
ListView {
id: listViewSettings
currentIndex: -1
interactive: false
spacing: 10
Layout.fillWidth: true
Layout.fillHeight: true
delegate: ItemDelegate {
height: 40
anchors {
left: parent.left
right: parent.right
}
highlighted: ListView.isCurrentItem
// Style of button
background: Rectangle {
color: parent.hovered ? "#555e69" : "transparent"
radius: 10
}
RowLayout {
anchors.fill: parent
spacing: 15
// Image
Rectangle {
color: noColor
Layout.minimumHeight: 30
Layout.minimumWidth: 30
Layout.leftMargin: 15
Layout.alignment: Qt.AlignRight
Image {
anchors.fill: parent
source: model.imageSource
}
}
// Text
Rectangle {
color: "transparent"
Layout.fillHeight: true
Layout.minimumWidth: 150
Layout.alignment: Qt.AlignLeft
Text {
anchors.verticalCenter: parent.verticalCenter
text: model.title
color: textColor
font.pixelSize: 16
}
}
}
onClicked: stackViewSettings.push(model.source)
}
model: ListModel {
ListElement { title: "Change profile"; imageSource: "ADD YOUR ICO"; source: "ADD YOUR PAGE" }
ListElement { title: "Language"; imageSource: "ADD YOUR ICO"; source: "ADD YOUR PAGE" }
}
}
}
}
}
}
}
Upd 1: I don't think I should use the stackview on dialog at all.
Upd 2: Just added clip: true in the StackView and It helped me.
Your problem is just a clipping issue. By default all QML objects have clip set to false, but you can turn it on to solve your problem:
StackView {
...
clip: true
}

I want to Align an item to the right in qml

Column {
id:column
spacing: 10
width: parent.width
Repeater{
model:5
Row {
leftPadding:17
topPadding:10
spacing: 10
Image {
id:img
height: 50
width: 50
source:"icon.png"
}
Text {
text:"User_name"
topPadding:12
}
Rectangle{
height: 40
width:40
color: "#333333"
Layout.alignment: Qt.AlignRight
}
}
}
}
I have Used Layout.alignment: Qt.AlignRight to show the rectangle to the right, But its not working. I don't understand why It is not working, I have also tried Layout.fillWidth: true inside an Item but still not working
As #Amfasis pointed out, Layout.alignment doesn't do anything unless you're using one of QML's layout types. Here's a working example using RowLayout/ColumnLayout:
ColumnLayout {
id:column
spacing: 10
width: parent.width
Repeater{
model:5
RowLayout {
Layout.leftMargin: 17
Layout.topMargin: 10
spacing: 10
Image {
id:img
source:"icon.png"
Layout.preferredWidth: 50
Layout.preferredHeight: 50
}
Text {
text:"User_name"
topPadding:12
Layout.fillWidth: true
}
Rectangle{
color: "#333333"
Layout.preferredHeight: 40
Layout.preferredWidth: 40
Layout.alignment: Qt.AlignRight
}
}
}
}

How to align items in RowLayout

I want to align Rectangles in a RowLayout left to right. In below code example two Rectangles share additional space instead stack one after another. I used Layout.alignment: Qt.AlignLeft in RowLayout level and Rectangle level, but non of those two ways didn't change the view at all.
Item {
RowLayout {
anchors.fill: parent
spacing: 2
Rectangle {
width: 100
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
Text {
text: "Hello world"
}
}
Rectangle {
width: 100
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
Text {
text: "Hello world"
}
}
}
}
In following images black border indicates the RowLayout and red border is the Rectangles.
Actual
Expected
The documentation states regarding the Layout.alignment:
This property allows you to specify the alignment of an item within the cell(s) it occupies.
You can simply add a filler item at the end like such:
RowLayout {
anchors.fill: parent
spacing: 2
Rectangle {
width: 100
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
color: 'red'
Text {
text: "Hello world"
}
}
Rectangle {
width: 100
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
color: 'green'
Text {
text: "Hello world"
}
}
Item {
Layout.fillWidth: true
}
}
But alternatively use that:
Row {
anchors.fill: parent
spacing: 2
Rectangle {
width: 100
anchors {
top: parent.top
bottom: parent.bottom
}
color: 'red'
Text {
text: "Hello world"
}
}
Rectangle {
width: 100
anchors {
top: parent.top
bottom: parent.bottom
}
color: 'green'
Text {
text: "Hello world"
}
}
}
You could change the spacing value to a negative like below :
RowLayout {
anchors.fill: parent
spacing: -parent.width*0.6
Rectangle {
width: 100
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
border.width:1
border.color:"red"
Text {
text: "Hello world"
}
}
Rectangle {
width: 100
Layout.fillHeight: true
Layout.alignment: Qt.AlignLeft
border.width:1
border.color:"red"
Text {
text: "Hello world"
}
}
}

How to design a multi-level fluid layout in QML

I have designed a layout in QML to learn more about its features and have some questions on the "Best Practices" in designing such layout. Here it is:
It is essentially a ColumnLayout consisted of three RowLayouts, each one with some Rectangles. The size of each Row and Rectangle should be calculate such as:
First row: Height = 40%, Width = 100%
Red Rectangle filling the whole area
Second row: Height = 20%, Width = 100%
Dark-green Rectangle: Height = 100%, Width = 20%,
Light-green Rectangle: Height = 100%, Width = 80%
Third row: Height = 40%, Width = 100%
Dark-blue Rectangle: Height = 100%, Width = 40%,
Blue Rectangle: Height = 100%, Width = 20%
Light-blue Rectangle: Height = 100%, Width = 40%
The QML I have came up with is working and is in the following. I have some questions about it:
I have set the width and height percentages using Layout.preferredHeight: x*parent.height pattern. Other options caused some issues (e.g. preferredHeight caused binding loop warnings). Is my approach correct and efficient?
As a hack, I set Layout.fillWidth: true for the first element of Row #2 and Row #3, which doesn't make sense to me, but does work. If I set their width as percentage (e.g. Layout.preferredWidth: 0.2*parent.width) their row will collapse to width 0. Is this an expected behavior? Is there any better workaround?
Do you have any recommendation on the layouts? Am I on the right path?
Here is my QML code for the layout:
ApplicationWindow {
x: 500
y: 100
width: 250
height: 150
visible: true
ColumnLayout {
anchors.fill: parent
spacing: 0
RowLayout {
spacing: 0
Layout.preferredHeight: 0.4*parent.height
Layout.fillHeight: false
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
color: "red"
}
}
RowLayout {
spacing: 0
Layout.preferredHeight: 0.2*parent.height
Layout.fillHeight: false
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
color: "darkGreen"
}
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: 0.8*parent.width
color: "lightGreen"
}
}
RowLayout {
spacing: 0
Layout.preferredHeight: 0.4*parent.height
Layout.fillHeight: false
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
color: "darkBlue"
}
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: 0.2*parent.width
color: "blue"
}
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: 0.4*parent.width
color: "lightBlue"
}
}
}
}
Update:
My approach seems to be more hacky than I expected:
Putting Text elements as children in this layout raises binding loop warnings like:
QML QQuickLayoutAttached: Binding loop detected for property "preferredWidth"
If a wrap Text inside a Rectangle the warnings disappear.
The spacing: 0 seems to play an important role. Omitting it will causes binding loop warnings.
While my approach to fluid layout design in QML works, it has some serious issue and might not fall under the "best practices".
While both other answers show valid solutions, I believe both the question being asked and the two solutions somehow miss the point of using Layouts.
Basically, Layouts are made to bring together Items that have an implicit size (implicitHeight/implicitWidth). Layout.preferredWidth/Layout.preferredHeight are used to override these things in some rare situations, see below. The "Qt Quick Layouts - Basic Example" coming with Qt does not use Layout.preferredWidth/Layout.preferredHeight at all (!) and makes a really nice look, without contaminating the whole qml file with either anchors or Layout properties. It takes some learning to be able to do this oneself, but once you got used to it, Layouts are a way to define user interfaces more directly with less code.
What confused me the most at the beginning were the following things:
RowLayout/ColumnLayout/GridLayout come with Layout.fillWidth/Layout.fillHeight set to true, so when putting these near an Item/Rectangle then the Items/Rectangles suddenly disappear, because they don't have set these values (i.e. they have Layout.fillWidth/Layout.fillHeight set to false).
Items/Rectangles come with an implicitHeight/implicitWidth of 0, meaning they don't really play nice side-by-side with Layouts. The best thing to do is to derive implicitWidth/implicitHeight from contained subitems, like a RowLayout/ColumnLayout itself does by default for its subitems.
Layout.preferredWidth/Layout.preferredHeight can be used to overcome implicit sizes where they are already defined and cannot be set. One such place is directly in a layout item, another is e.g. a Text item which also doesn't let you override implicit sizes.
Considering these points, I would write the example in the following way. I removed unnecessary items to better illustrate when Layout.fillwidth/Layout.fillheight are needed, and when it is better to use implicitWidth in my opinion.
import QtQuick 2.9
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
width: 250
height: 150
visible: true
ColumnLayout {
spacing: 0
anchors.fill: parent
Rectangle {
implicitHeight: 40
Layout.fillHeight: true
Layout.fillWidth: true
color: "red"
}
RowLayout {
spacing: 0
Layout.preferredHeight: 20
Rectangle {
implicitWidth: 20
Layout.fillHeight: true
Layout.fillWidth: true
color: "darkGreen"
}
Rectangle {
implicitWidth: 80
Layout.fillHeight: true
Layout.fillWidth: true
color: "lightGreen"
}
}
RowLayout {
spacing: 0
Layout.preferredHeight: 40
Rectangle {
implicitWidth: 40
Layout.fillHeight: true
Layout.fillWidth: true
color: "darkBlue"
}
Rectangle {
implicitWidth: 20
Layout.fillHeight: true
Layout.fillWidth: true
color: "blue"
}
Rectangle {
implicitWidth: 40
Layout.fillHeight: true
Layout.fillWidth: true
color: "lightBlue"
}
}
}
}
It is forbidden (and unnecessary) to try and reference width and height of the parent from Items inside the Layout.
When fillWidth (or fillHeight) is set to true, then Items are allocated space in proportion to their specified preferredWidth (or preferredHeight).
Therefore the correct way to create your Layout is as follows. I have modified the appearance only to show that spacing and Text can also be set freely as desired. No binding loops.
ApplicationWindow {
x: 500
y: 100
width: 250
height: 150
visible: true
ColumnLayout {
anchors.fill: parent
spacing: 5
RowLayout {
spacing: 5
Layout.preferredHeight: 40
Layout.fillHeight: true
Rectangle {
Layout.fillHeight: true
Layout.fillWidth: true
color: "red"
}
}
RowLayout {
spacing: 5
Layout.preferredHeight: 20
Layout.fillHeight: true
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: 20
Layout.fillWidth: true
color: "darkGreen"
}
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: 80
Layout.fillWidth: true
color: "lightGreen"
}
}
RowLayout {
spacing: 5
Layout.preferredHeight: 40
Layout.fillHeight: true
Text {
Layout.fillHeight: true
Layout.preferredWidth: 40
Layout.fillWidth: true
color: "darkBlue"
text: "hello world!"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: 20
Layout.fillWidth: true
color: "blue"
}
Rectangle {
Layout.fillHeight: true
Layout.preferredWidth: 40
Layout.fillWidth: true
color: "lightBlue"
}
}
}
}
QtQuick.Layout does not provide any real improvements over the classical anchoring system. I would recommand to avoid them. You can have way more control over your layout using anchors.
Here is the exact same design without QtQuick.Layout :
ApplicationWindow {
x: 500
y: 100
width: 250
height: 150
visible: true
Column {
anchors.fill: parent
Row {
anchors.left: parent.left
anchors.right: parent.right
height: 0.4 * parent.height
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width
color: "red"
}
}
Row {
anchors.left: parent.left
anchors.right: parent.right
height: 0.2 * parent.height
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 0.2 * parent.width
color: "darkGreen"
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 0.8 * parent.width
color: "lightGreen"
}
}
Row {
anchors.left: parent.left
anchors.right: parent.right
height: 0.4 * parent.height
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 0.4 * parent.width
color: "darkBlue"
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 0.2 * parent.width
color: "blue"
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 0.4 * parent.width
color: "lightBlue"
}
}
}
}
So far I never met any design that was impossible to do without QtQuick.Layout.

Editing a TextInput in a ScrollView

I have an issue with my QML. I'd like to edit a TextInput based on an action, setting the focus attribute to true. It works when the TextInput is located in a Rectangle, but not in a ScrollView.
Here is an example:
Item {
id: main
width: 640
height: 480
ScrollView{
id: scrollView
height: parent.height/2
width: parent.width
Rectangle{
border.color: "black"
border.width: 1
anchors.centerIn: parent
height: 25
width: 200
TextInput{
id: ti1
anchors.fill: parent
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: TextInput.AlignHCenter
}
}
}
Rectangle{
y: height
height: parent.height/2
width: parent.width
Rectangle{
border.color: "black"
border.width: 1
anchors.centerIn: parent
height: 25
width: 200
TextInput{
id: ti2
anchors.fill: parent
verticalAlignment: TextInput.AlignVCenter
horizontalAlignment: TextInput.AlignHCenter
}
}
}
MouseArea{
anchors.fill: parent
onClicked: {
if (mouseY < parent.height/2){
ti2.focus = false
ti1.focus = true
}else{
ti1.focus = false
ti2.focus = true
}
}
}
}
When I click on the bottom half of the window, the TextInput ti2 is editable. But when I click on the top half, ti1 is not.
Does anybody have any idea? The behaviour is the same with TextEdit.
Thanks.
I think it is because:
"Only one Item can be a direct child of the ScrollView and the child is implicitly anchored to fill the scroll view.".
From: http://doc.qt.io/qt-5/qml-qtquick-controls-scrollview.html
Perhaps the tree of components is unavailable in a ScrollView.
But if you use:
ti1.forceActiveFocus();
instead of:
ti1.focus = true
it works.

Resources