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 ...
}
}
}
}
}
}
}
Related
I'm creating a component in QML, works fine but I want the TEXT field to be in the center of rectangle. For that I've anchored it accordingly but the anchor doesn't work. I don't know why.
Item {
id: root
property int main_rect_height: 32
property int elem_txt_size: 14
property string elem_border_color: "red"
property int elem_width: parent.width/6.5
Rectangle {
id: clients_rect
width: root.parent.width-27
height: main_rect_height
color: "transparent"
border.color: "black"
Rectangle {
id: username_rect
width: elem_width
height: parent.height
color: "transparent"
border.color: elem_border_color
Text {
id: username_txt
text: "USERNAME"
font.pixelSize: elem_txt_size
anchors {
fill: parent
centerIn: parent // THIS DOESN'T WORK!
}
}
}
}
By using anchors.fill: parent, you're setting the size and position of the Text object to match the parent. Centering an object of the same size won't do anything because it already takes up the entire space of the parent. And by default, the text is aligned to the top and left. You have two options:
You can use Text's alignment properties to align the text within itself to be centered:
Text {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Or, you can simply use centerIn without the fill.
Text {
anchors.centerIn: parent
}
I have a ListView that contains a list of rectangles with text. Sometimes the text in the Rectangles is too long to fit so I would like the text to scrollable horizontally. I'm using a ScrollView surrounding the text to make it horizontally scrollable.
The problem is, I can't scroll through the list (vertically) because the scrolling gets intercepted by the horizontal ScrollViews.
Here is what my qml looks like:
ListView { //vertically scrolling list
model: modelName
anchors.fill: parent
id: vListView
delegate: Column {
width: parent.width
spacing: 3
bottomPadding: 2
Rectangle { // rectangles containing the text
width: parent.width
height: 40
radius: 5
id: buttonName
ScrollView {//horizontally scrolling list
contentHeight: -1
anchors.fill: parent
anchors.leftMargin: 18
id: hScrollView
Text {// text that is sometimes too long
width: parent.width
rightPadding: 15
bottomPadding: 5
text: model.data
topPadding: 9
horizontalAlignment: Text.AlignLeft
anchors.centerIn: parent
}
}
}
}
}
How can I get the list to scroll vertically and have the individual text boxes also scroll horizontally?
edit:
I've tried to use the following code to "catch" the scroll-wheel input and scroll the appropriate elements. But I hasn't been working out.
(code is placed in a mouse area that fills the whole thing)
onWheel: {
if (wheel.angleDelta.y > 0) {
vListView.flickableItem.contentX -= vListView.scrollSpeed;
if (vListView.flickableItem.contentX < 0) {
vListView.flickableItem.contentX = 0;
}
} else {
hScrollView.flickableItem.contentX += hScrollView.scrollSpeed;
if (individualCommandScrollView.flickableItem.contentX + hScrollView.flickableItem.width > hScrollView.flickableItem.contentWidth) {
hScrollView.flickableItem.contentX = hScrollView.flickableItem.contentWidth - hScrollView.flickableItem.width;
}
}
}
onClicked: mouse.accepted = false;
onPressed: mouse.accepted =
onReleased: mouse.accepted = false;
onDoubleClicked: mouse.accepted = false;
onPositionChanged: mouse.accepted = false;
onPressAndHold: mouse.accepted = false;
See the following solution using a Flickable instead of a ScrollView and a MouseArea to manually propagate the scroll to the horizontal Flickable when required.
The Flickable will not steal the mouse event from the parent ListView if the horizontal scroll on the text is not necessary.
Note that if all the texts are too long, you will never be able to scroll vertically on the main ListView...
I would recommend to imagine another design to handle long texts (text elide, wrap, multiline, ...).
ListView {
id: vListView
// ...
delegate: Rectangle {
width: parent.width
height: 40
radius: 5
Flickable {
id: hScrollView
contentHeight: -1
contentWidth: text.paintedWidth // <===== to allow horizontal scroll
interactive: contentWidth > width // <===== but only if text is too long
anchors.fill: parent
anchors.leftMargin: 18
Text {
id: text
width: parent.width
rightPadding: 15
bottomPadding: 5
text: model.data
topPadding: 9
horizontalAlignment: Text.AlignLeft
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
enabled: hScrollView.interactive
// manually scroll in Flickable on mouse wheel
onWheel: {
let velocity = vListView.highlightMoveVelocity // use same velocity as the vertical ListView
let scrollValue = wheel.angleDelta.y >= 0 ? velocity : -velocity // move left or right according to wheel value
hScrollView.flick(scrollValue, 0)
}
}
}
}
}
Try to add this to ListView:
ScrollBar.vertical: ScrollBar {}
Or add some margin to Rectangle and add borders or color to see where it is. So you will be able to point outside it and scroll ListView
I have a QML ColumnLayout with a few children, and I want to limit its width, like so:
ColumnLayout {
width: 360
height: 480
ColumnLayout {
id: inner
Layout.maximumWidth: 200
Layout.fillHeight: true
Text {
text: "Welcome"
font.pixelSize: 18
}
Text {
text: "Long explanation that should wrap, but ends up overflowing layout"
wrapMode: Text.WrapAnywhere
}
}
Rectangle {
anchors.fill: inner
z: -1
border.color: "orange"
}
}
I get the result shown in the picture below.
The orange box shows the dimensions of the inner layout item, which is all right. However, the children text of the layout is not wrapped.
I can only fix that by adding
Layout.maximumWidth: parent.width
to my 'Text' items, but that's quite awkward approach. Am I doing anything wrong, or is this a Qt bug, or is it a design approach for some reason? I am using Qt 5.4.1.
The text will only wrap if an explicit width has been set
Docs
Text
{
width: parent.width
}
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.
How is it possible in QML to automatically stretch element so that all its childs fit in it? And how to specify spacing? For example, I would like to have a rectangle around a text. The rectangle should have some internal spacing.
If I write the following then the rectangle has a size of 0,0.
Rectangle {
color: "gray"
anchors.centerIn: parent;
Text {
text: "Hello"
}
}
If I try to fix it by using the Column element, as suggested in How to make QML items to grow to fit contents?, then I get a column through the whole window/parent,
Column {
anchors.centerIn: parent
Rectangle {
color: "gray"
anchors.fill: parent
}
Text {
anchors.centerIn: parent
text: "Hello"
}
}
Edit:
I have also tried to use the Flow element instead of Column, but then I got a row through the whole window/parent.
You can use the childrenRect property for this:
import QtQuick 2.0
Rectangle {
width: 320
height: 200
Rectangle {
color: "BurlyWood"
anchors.centerIn: parent
width: childrenRect.width + 20
height: childrenRect.height + 20
Text {
id: hello
x: 10
y: 10
text: "Hello"
}
Text {
anchors.left: hello.right
anchors.leftMargin: 10
anchors.top: hello.top
text: "World"
}
}
}
However, note that using childrenRect in combination with using anchors.centerIn: parent in one of the direct children yields a warning about a binding loop.
Setting the width and height manually works, but is a little ugly:
Rectangle {
color: "gray"
width: label.width+20
height: label.height+20
anchors.centerIn: parent
Text {
id: label
anchors.centerIn: parent
text: "Hello"
}
}
I don't think using chilrenRect property is sufficient (as suggested by Thorbjørn Lindeijer). It doesn't automatically take into account all various margins of the child(ren) element(s). If the latter changes, the root rectangle doesn't automatically adjust its size. I personally came with the following solution:
Rectangle {
color: "white"
implicitWidth: row.implicitWidth + extraLeft + extraRight
implicitHeight: row.implicitHeight + extraTop + extraBottom
property int extraMargin: row.anchors.margins ? row.anchors.margins : 0
property int extraTop: row.anchors.topMargin ? row.anchors.topMargin : extraMargin
property int extraBottom: row.anchors.bottomMargin ? row.anchors.bottomMargin : extraMargin
property int extraLeft: row.anchors.leftMargin ? row.anchors.leftMargin : extraMargin
property int extraRight: row.anchors.rightMargin ? row.anchors.rightMargin : extraMargin
RowLayout {
id: row
spacing: 50
anchors.fill:parent
anchors.margins: 50
anchors.leftMargin: 100
Label {
text: "hello"
}
Label {
text: "world"
}
}
}