What is the difference between Row and RowLayout? - qt

This works as intended with Row, but not with RowLayout. Why? What is the difference between the two?
ApplicationWindow {
title: "Testing"
width: 640
height: 480
//RowLayout {
Row {
anchors.fill: parent
Rectangle {
id: rect1
width: parent.width * 0.3
height: parent.height
color: "blue"
}
Rectangle {
height: parent.height
width: parent.width * 0.7
color: "red"
}
}
}

Row is a Item Positioner. Positioner items are container items that manage the positions of items in a declarative user interface.
RowLayout is part of Qt Quick Layouts. They manage both the positions and the sizes of items on a declarative user interface, and are well suited for resizable user interfaces.
Your code with RowLayout should look like this:
RowLayout{
anchors.fill: parent
spacing: 0
Rectangle{
Layout.fillHeight: true
Layout.preferredWidth: parent.width * 0.3
color: "blue"
}
Rectangle{
Layout.fillHeight: true
Layout.fillWidth: true
color: "red"
}
}

I think
Row is a container which grows the size based on the children of Row, making them line up as a row, so the children of it shall have size.
RowLayout is the wrapper of its children, giving them the ability of row positioning and resizing based on the size of RowLayout, so RowLayout shall have its own size to help the children to position and resize.

Related

Looking for alternate function to QML ListView's itemAtIndex due to version conflict

I'm using Qt 5.12, so I can't access ListView's itemAtIndex which was introduced in Qt 5.13.
I can't upgrade Qt due to my project/platform related restrictions. Is there a way to find the item at a given index for ListView with the Qt versions prior to 5.13?
Otherwise, is there a way to get mouse positions of an item based on index?
I'm having a listview with adjacent items having different width(alternate items have same width). I'm trying to access listview's item which is of less width compared to the adjacent item. The space between two items in the above picture is also an item which is marked as dummy. I'm able to get the index of each item (both actual & dummy), but the x position I get seems to be incorrect as the rectangle cursor is not getting placed in the intended item's position.
Please suggest alternatives that gives the similar functionality as itemAtIndex. Thanks.
In the following example, I declare a MouseArea in each delegate. So, once the mouse hovers over that delegate, we trigger MouseArea.onEntered and can know which item, because that delegate will have the corresponding index value:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
background: Rectangle { color: "#848895" }
ColumnLayout {
anchors.fill: parent
ListView {
id: listView
Layout.fillWidth: true
Layout.preferredHeight: 150
model: 20
orientation: ListView.Horizontal
delegate: MyDelegate { }
ScrollBar.horizontal: ScrollBar {
height: 20
policy: ScrollBar.AlwaysOn
}
highlight: Item {
z: 2
Rectangle {
width: 10
height: parent.height
color: "lightsteelblue"
border.color: "black"
}
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
Frame {
anchors.centerIn: parent
background: Rectangle { }
Text {
text: qsTr("ListView.currentIndex = %1").arg(listView.currentIndex)
}
}
}
}
}
// MyDelegate.qml
import QtQuick
import QtQuick.Controls
Rectangle {
property ListView listView: ListView.view
width: 120
height: listView.height - 20
implicitWidth: width
implicitHeight: height
color: "transparent"
Rectangle {
border.color: "grey"
color: "white"
y: 20
height: parent.height - y * 2
width: parent.width
Text {
anchors.centerIn: parent
text: qsTr("Item %1").arg(modelData + 1)
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: listView.currentIndex = index
}
}
You can Try it Online!

How to increase height of Rectangle according to text in QML

I am not able to increase height of Rectangle (or RowLayout) wrapped around Text item that could dynamically change (chat message for example).
I tried bunch of approaches (Text.paintedHeight, childrenRect ...) but everything looks funky when text is wrapped.
My goal is display chat messages, stretch them according their wrapped text height.
Thanks for any input.
import QtQuick 2.0
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true
width: 900
height: 500
ColumnLayout {
width: parent.width
spacing: 2
RowLayout {
id: rowLayout
spacing: 3
Rectangle {
height: 50
width: 50
color: "red"
}
Rectangle {
id: rectangle
width: 50
color: "green"
Layout.fillHeight: true
Layout.fillWidth: true
Text {
id: element
text: "If the GridLayout is resized, all items in the layout will be rearranged. It is similar to the widget-based QGridLayout. All visible children of the GridLayout element will belong to the layout. If you want a layout with just one row or one column, you can use the RowLayout or ColumnLayout. These offer a bit more convenient API, and improve readability.\n\nBy default items will be arranged according to the flow property. The default value of the flow property is GridLayout.LeftToRight.\n\nIf the columns property is specified, it will be treated as a maximum limit of how many columns the layout can have, before the auto-positioning wraps back to the beginning of the next row. The columns property is only used when flow is GridLayout.LeftToRight."
anchors.rightMargin: 10
anchors.leftMargin: 10
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
wrapMode: Text.WordWrap
clip: false
font.pixelSize: 12
}
}
}
}
}
You have to specify the implicitHeight and implicitWidth for Rectangle (and Item for that matter).
Rectangle {
id: rectangle
width: 50
color: "green"
Layout.fillHeight: true
Layout.fillWidth: true
implicitWidth: element.implicitWidth
implicitHeight: element.implicitHeight
Text {
id: element
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
wrapMode: Text.WordWrap
clip: false
font.pixelSize: 12
}
}
Please note that your current setup with anchors.margins is slightly conflicting here, since that is not counted in the implicitHeight/Width, so I left them out.
Another option would be to set the background for a Label (from QtQuick.Controls) to your desired Rectangle, that will then be stretched properly:
Label {
leftPadding: 10
rightPadding: 10
...
background: Rectangle {
color: "green"
}
}
In my opinion this would give you easier control about the position of your text.

QML: Setting a row width in a ListView

I have a page with a ListView in a layout. The ListView consists of several rows represented with Rectangles and a RowLayout in it. The RowLayout itself consists of Text elements. The problem which I'm facing is that I can't properly set the width of these Text elements. E.g. I want the first Text element to have a 1/3 width of the whole row. The way I'm setting it now makes the Text element width to be cca 3/4 of the row width, at least visually it looks like that. What would be the proper way of setting the Text element width?
Item {
ColumnLayout {
anchors.fill: parent
// some components here ...
Rectangle {
width: parent.width
Layout.fillWidth: true
Layout.fillWidth: true
Rectangle {
anchors.fill: parent
anchors.margins: 0.1 * parent.height
ListView {
id: listView
anchors.fill: parent
model: SomeModel {}
delegate: Rectangle {
height: 40
width: listView.width
RowLayout {
width: listView.width
Text {
Layout.preferredWidth: 0.3 * listView.width
text: "text1"
}
Text {
text: "text2"
}
// some other Text elements ...
}
}
}
}
}
}
}

Qt QML anchor not working in custom Item

I'm new of qml.
I'm starting to develop a little application with a custom item.
when I try to use in application anchor.top: first_item.bottom, to position the rectangles of the custom component, one below the other doesn't work.
content file main.qml:
import QtQuick 2.5
Item
{
id:main_screen
Rectangle
{
width: 300
height: 60
id: text_content
color: "DarkGray"
opacity: 0.9
border.color: "blue"
border.width: 3
radius: 5
z:6
Text {
id: titleText
width: parent.width
height: parent.height
font.pointSize: 20
font.family: "Arial"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: "Test - title"
color: "White"; style: Text.Raised;
}
}
//..................This rectangle is shown below main_screen... so is OK
Custom_item
{
id:first_item
anchors.top: main_screen.bottom
}
//..................This rectangle is not shown below first_item... but it shown on absolute top, in overlap of retangle title
Custom_item
{
id:second_item
anchors.top: first_item.bottom
}
//..................This rectangle is not shown below second_item... but it shown on absolute top, in overlap of retangle title
Custom_item
{
id:third_item
anchors.top: second_item.bottom
}
}
content file Custom_item.qml
import QtQuick 2.5
Item
{
id:testComponent
Rectangle
{
width: 300
height: 60
id: text_content
color: "DarkGray"
opacity: 0.9
border.color: "blue"
border.width: 3
radius: 5
z:6
}
}
what am I doing wrong ?
Thanks
The problem lies within the dimensions of the objects your are anchoring to.
Though the Rectangles have a width and a height, the enclosing Item has none, so it is basically 0 pixels in height and width, while the Rectangle protrudes it.
If you don't have any reason for enclosing the Rectangle within the Item, I'd reccomend you, to take the Rectangle itself as the toplevel element of the file.
Reasons for having the Item might be those:
Hiding the Rectangles properties
Having multiple children for the Item that are logically siblings to the Rectangle
... other reasons might exist ;-)
Nevertheless, you need to make sure, that the toplevel item has always the right dimensions. So you should set the width and height, better the implicitWidth and implicitHeight in component declarations.
Example 1: Without an Item
import QtQuick 2.5
Rectangle {
id: root
width: 300
height: 60
color: "DarkGray"
opacity: 0.9
border.color: "blue"
border.width: 3
radius: 5
z:6
}
Example 2: With Item
import QtQuick 2.5
Item {
id:testComponent
implicitHeight: 60 // < This
implicitWidth: 300 // < and that are important to have the dimensions
Rectangle {
id: text_content
anchors.fill: parent
color: "DarkGray"
opacity: 0.9
border.color: "blue"
border.width: 3
radius: 5
z:6
}
}
You are anchoring all the Rectangle's to the Item hence you are not getting the desired result. Simple change the id of the top Rectangle as follows
Item
{
id: root
Rectangle
{
id:main_screen
...
}
}

Why does anchors.fill does not work in a QML ListView's delegate's subviews, and what is a nice solution?

I encountered this:
ListView {
id: listView
model: ["Lorem","Ipsum"]
delegate: Item {
height: 20
Text {
z: 2
text: modelData
anchors.fill: parent
}
Rectangle {
z: 1
color: "red"
// this does not work:
anchors.fill: parent
// this works, but I have mixed feelings about it:
// height: 20; width: listView.width
}
}
}
So, apparently, anchors do not work in a delegate's subitem (in this case, Rectangle is not displayed at all). I would like to understand the mechanism behind this. Also, I'd like to ask what is the preferred way to deal with this situation?
Thank You!
Item has an implicitWidth and implicitHeight of zero, so making your Rectangle and Text fill it will result in them having no size as well.
There are two things wrong with your code:
The ListView has no width or height specified.
Your delegate has no width specified.
Here's one way of doing it correctly:
import QtQuick 2.0
import QtQuick.Window 2.0
Window {
width: 300
height: 300
visible: true
ListView {
id: listView
anchors.fill: parent
model: ["Lorem","Ipsum"]
delegate: Item {
width: listView.width
height: textItem.implicitHeight
Text {
id: textItem
z: 2
text: modelData
width: parent.width
}
Rectangle {
z: 1
color: "red"
anchors.fill: parent
}
}
}
}
The documentation of ListView has more information.

Resources