I need to create a long form using QML. The form will not fit inside the window, so I need for it to be scrollable. However I can't get the scroll view to work. Here is a minimum working example of my problem:
import QtQuick.Window 2.2
import QtQuick 2.9
import QtQuick.Controls 2.3
Window {
visible: true
width: 1280
height: 720
title: qsTr("Hello World")
Rectangle{
anchors.centerIn: parent
width: parent.width*0.8;
height: parent.height*0.7;
ScrollView {
anchors.fill: parent
clip: true
contentHeight: parent.height
Rectangle{
id: rect1
width: parent.width
height: 200
color: "#ffff00"
anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle{
id: rect2
width: parent.width
height: 500
color: "#ff00ff"
anchors.top: rect1.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle{
id: rect3
width: parent.width
height: 500
color: "#00ffff"
anchors.top: rect2.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
As I understand it, this should allow me to scroll in order to see the 3 rectangles. However I only the see the first one and the upper half of the second one and I can't scroll.
Any help would be greatly appriciated
Because your ScrollView contains multiple items you need to take care of sizing yourself and set contentHeight explicitly to the combined height of all the items.
For testing, you can set vertical scrollbar always on to see how content height affects the scrollbar.
I commented out horizontal center anchoring because it is not needed (width of your rectangles is scrollview width).
ScrollView {
anchors.fill: parent
clip: true
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
contentHeight: rect1.height+rect2.height+rect3.height
Rectangle{
id: rect1
width: parent.width
height: 200
color: "#ffff00"
//anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle{
id: rect2
width: parent.width
height: 500
color: "#ff00ff"
anchors.top: rect1.bottom
//anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle{
id: rect3
width: parent.width
height: 500
color: "#00ffff"
anchors.top: rect2.bottom
//anchors.horizontalCenter: parent.horizontalCenter
}
}
If you wrap your rectangles with an item and set item implicitHeight to its height ScrollView detects the contentHeight correctly.
ScrollView {
anchors.fill: parent
clip: true
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
Item {
width: parent.width
height: rect1.height+rect2.height+rect3.height
implicitHeight: height
Rectangle{
id: rect1
width: parent.width
height: 200
color: "#ffff00"
}
Rectangle{
id: rect2
width: parent.width
height: 500
color: "#ff00ff"
anchors.top: rect1.bottom
}
Rectangle{
id: rect3
width: parent.width
height: 500
color: "#00ffff"
anchors.top: rect2.bottom
}
}
}
The default implicit size for most items is 0x0, that's why you have to set implicit height for the item explicitly. However some items have an inherent implicit size, e.g. Image and Text. This means that if you place e.g. TextArea into your ScrollView it will automatically become scrollable if text is long enough.
ScrollView {
anchors.fill: parent
clip: true
TextArea {
readOnly: true
text: online ? provider.loadedText : "Offline"
wrapMode: Text.WordWrap
}
}
Set the height and width of the scrollview to be the total of childs height added together!
Related
I can't figure out why my ToolButton is so small. The ToolBar is the orange rectangle on the top. The following code:
Item{
ToolBar{
id: toolbar
width: parent.width
height: scaleDP(0.29)
anchors.top: parent.top
background: Rectangle{
color: "orange"
}
RowLayout{
anchors.fill: parent
ToolButton {
id: buttonBack
height: parent.height
width: parent.height
Image {
id: imageBack
source: "qrc:/assets/images/left-filled-black-50.png"
anchors.fill: parent
anchors.margins: 4
}
}
Shows my ToolButton so small:
I can change the height of the Image and makes it bigger but then its outside the ToolButton. When I try to resize the height of the ToolButton, nothing happens
Findings
It seems the issue is with RowLayout. If I change it to Row or Rectangle, then the icons resizes as expected.
The RowLayout uses its children's implicitHeight and implicitWidth, and ignores height and width. For some simple items (eg Rectangle), setting their height also changes their implicitHeight, but this is not the case for QuickControls like the ToolButton.
RowLayout{
height: 20
width: parent.width
// WON'T WORK
ToolButton {
id: buttonBack1
height: parent.height
width: parent.height
}
// OK
ToolButton {
id: buttonBack2
Layout.preferredHeight: parent.height
Layout.preferredWidth: parent.height
}
// OK TOO
ToolButton {
id: buttonBack3
implicitHeight: parent.height
implicitWidth: parent.height
}
}
If you still need a RowLayout, you have two options:
Set implicitHeigt and implicitWidth or
Use the Layout's attached properties: Layout.preferredHeight & Layout.preferredWidth
I am using Row to layout some buttons on a Rectangle which is my custom toolbar implementation. The problem is no matter what I do, the components are always aligned from the left. I would like them to be aligned with the center of the row and flowing outwards towards the edges. The code looks as follows:
Rectangle {
id: toolbar
color: "green"
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 100
Row
{
anchors.fill: parent
anchors.horizontalCenter: parent.horizontalCenter
spacing: 60
ToolButton {
height: parent.height
Image {
anchors.verticalCenter: parent.verticalCenter
source: "../images/image.png"
}
}
ToolButton {
height: parent.height
Image {
anchors.verticalCenter: parent.verticalCenter
source: "../images/image.png"
}
}
}
}
My buttons are always laid out starting from the left side of the row. Rather I would like to have them laid out relative to the center of the toolbar. I thought specifying this line anchors.horizontalCenter: parent.horizontalCenter should achieve that but no matter what I try, the components are laid out from the left boundary.
If you set your Row's alignments to center in the parent object and then make the Row's width adjust to the childrenRect's width then you can have items expand from the center of the object. Note: you may need to set the widths of the ToolButton's in order for the childrenRect to have it's width value populated.
Rectangle {
id: toolbar
color: "green"
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 100
Row
{
anchors{
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
height: parent.height
width: childrenRect.width
spacing: 60
ToolButton {
height: parent.height
width: 50
Image {
anchors.verticalCenter: parent.verticalCenter
source: "../images/image.png"
}
}
ToolButton {
height: parent.height
width: 50
Image {
anchors.verticalCenter: parent.verticalCenter
source: "../images/image.png"
}
}
}
}
You've set anchors.fill: parent on the Row so it will of course fill its parent. Instead, you should remove this, and only set height: parent.height on the Row.
Documentation citation:
since a Row automatically positions its children horizontally, a child item within a Row should not set its x position or horizontally anchor itself using the left, right, anchors.horizontalCenter, fill or centerIn anchors. If you need to perform these actions, consider positioning the items without the use of a Row.
Row is only for positioning it`s children horizontally. Without any 'flows' or centering. It is for automatic positioning in a row which let you exclude defines of anchors and margins inside item when you need to perform that simple task.
But if you need something more complicated, you need to do it with anchors and margins manually. For example. Centering items and spreading them from center to the edges might look like this:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
id: toolbar
color: "green"
anchors.centerIn: parent
height: 100
width: parent.width
Rectangle {
id: toolbutton1
height: parent.height
anchors {
right: toolbutton2.left
margins: 20
}
width: 100
color: "blue"
}
Rectangle {
id: toolbutton2
height: parent.height
anchors {
right: parent.horizontalCenter
margins: 10
}
width: 100
color: "magenta"
}
Rectangle {
id: toolbutton3
height: parent.height
anchors {
left: parent.horizontalCenter
margins: 10
}
width: 100
color: "red"
}
Rectangle {
id: toolbutton4
height: parent.height
anchors {
left: toolbutton3.right
margins: 20
}
width: 100
color: "yellow"
}
}
}
how can I center elements in ColumnLayout?
Here is my qml code:
ApplicationWindow {
id: root
visible: true
width: 640
height: 640
title: qsTr("Your Booking")
GridLayout{
anchors.fill: parent
columns: 2
flow: GridLayout.TopToBottom
Rectangle{
id: appBar
Layout.columnSpan: 2
width: root.width
height: root.height/10
color: "red"
}
ColumnLayout{
spacing:5
id: columnData
height: root.height - appBar.height
width: root.width/2
ComboBox{
anchors.horizontalCenter: parent.horizontalCenter
}
ComboBox{
}
ComboBox{
}
ComboBox{
}
ComboBox{
}
}
ColumnLayout{
}
}
}
I want to center ComboBoxes in ColumnLayout.
You should avoid using anchors and layouts at the same time. Mixing them at the same level would lead to the malfunction of the layouts or some unexpected results (however, using anchors inside the items in layouts is ok).
To align items in layouts, you can use the attached properties: Layout.alignment, e.g.:
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
This statement would make your item stay exactly in the center of your layout.
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.
I have a nested ScrollView, similar to the following QML:
import QtQuick 2.0
import QtQuick.Controls 1.1
Rectangle {
width: 200
height: 600
ScrollView {
id: sView
anchors.fill: parent
ListView {
id: list
boundsBehavior: Flickable.StopAtBounds
clip: true
focus: true
interactive: true
model: 5
delegate: Component {
MouseArea {
id: hoverArea
width: 100
height: 200
onClicked: list.currentIndex = index;
Rectangle {
id: fauxParent
anchors.fill: parent
border.width: 1
border.color: "black"
Rectangle {
anchors.top: parent.top
anchors.left: parent.left
height: parent.height
width: parent.width / 2
border.width: 1
border.color: "purple"
color: "green"
Text {
anchors.centerIn: parent
text: "stuff"
}
}
ScrollView {
//parent: sView
anchors.top: fauxParent.top
anchors.right: fauxParent.right
height: fauxParent.height
width: fauxParent.width / 2
ListView {
model: 3
delegate: Component {
Rectangle {
radius: 10
height: 100
width: 100
color: "blue"
}
}
}
}
}
}
}
}
}
}
It seems to run correctly, except that the inner ScrollView won't respond to the mousewheel: the outer ScrollView intercepts that event. The only fix I've found in research for this, is to set the inner scrollview's parent directly to the outer scrollview (uncomment the parent: sView line). Unfortunately, this re-positions all five scrollview delegates onto the top right corner of the outer scrollview. It seems that ScrollView positions itself based on its parent?
For the record, my actual application is wrapping a large section of the page in a scrollview so as to allow the user to access sections of it that may be out of bounds for the current window size. The content of this section, though, has a variety of different controls for a variety of different purposes, including some scrollviews. So I'd also accept an alternate way of moving around a set of generic content that's too large for the window.
This is a Windows desktop app, so I don't need to consider mobile-specific issues.
You nested four elements that handle scroll Events.
Why do you put a ScrollView arround a ListView?
If you remove the ScrollViews the Mousewheel work fine.
Rectangle {
width: 200
height: 600
ListView {
anchors.fill: parent
id: list
boundsBehavior: Flickable.StopAtBounds
clip: true
focus: true
interactive: true
model: 5
delegate: Component {
MouseArea {
id: hoverArea
width: 100
height: 200
onClicked: list.currentIndex = index;
Rectangle {
id: fauxParent
anchors.fill: parent
border.width: 1
border.color: "black"
Rectangle {
anchors.top: parent.top
anchors.left: parent.left
height: parent.height
width: parent.width / 2
border.width: 1
border.color: "purple"
color: "green"
Text {
anchors.centerIn: parent
text: "stuff"
}
}
ListView {
anchors.top: fauxParent.top
anchors.right: fauxParent.right
height: fauxParent.height
width: fauxParent.width / 2
model: 3
delegate: Component {
Rectangle {
radius: 10
height: 100
width: 100
color: "blue"
}
}
}
}
}
}
}
}
If you miss the Scrollbar look at this:
How to create scrollbar in QtQuick 2.0?