Set height of popup to contain contents - qt

I want to set the size (mainly height) of my popup to fit the contents depending on how much text is shown or whether there's an icon image shown on popup. How do I set the height of popup.
Eg.
Popup {
id: popup
width: window.width/2
height: window.height/4
x: window.width/2 - width/2
y: window.height/2 - height/2
Rectangle {
id: popupContent
width: parent.width
height: parent.height
visible: notification
anchors.fill: parent
Rectangle {
id: iconField
anchors.top: parent.top
width: parent.width
height: parent.height/2
Image {
id: img
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
width: window.width/18
height: window.width/18
fillMode: Image.PreserveAspectFit
source: "qrc:/images/icons/info.png"
}
}
Rectangle {
id: textField
anchors.top: iconField.bottom
width: parent.width
height: parent.height/2
Text {
id: text1
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignHCenter
width: parent.width
wrapMode: Text.WordWrap
text: "This long text overflows out of the popup up rectangle!"
}
}
}
}
If I use a long text then the text overflows from the popup rectangle. I tried using implicitHeight in different places but I don't understand how to apply it in this situation.

There's several issues with your code. It's hard to make a perfect answer because I don't know exactly what's intended. For example, your text will always be off the bottom of the Rectangle because you anchored textField's anchor.top to iconField.bottom, and iconField is the same size as the entire popup. But here's some ideas on how to improve it.
Your popupContent is a Rectangle, but I'm not sure if you actually are intending to draw a rectangle there or not. I think you could replace that with a ColumnLayout like the example here.
You can also manually specify the height of your content using the contentHeight property. You could set it to the height of your iconField plus the height of your textField, plus any padding you want.
Every Item has a property called childrenRect.height which will tell you the combined height of all of its children.
For all of these options though, you will need to stop setting every object's height to be the same as its parent's height.

Related

QML ScrollView does not scroll

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!

Wrong width and position of non-attached horizontal QML ScrollBar (and ScrollIndicator) when I resize parent element from RTL

The problem is in position and width of the horizontal scrollbar and position of the content that has been scrolled when I resize the width of the window (parent) element in RTL direction.
When I do these steps:
Resize the width of window in LTR direction.
Everything is working fine.
Change scrollbar position to any other position that is different from 0.0, (for example move it all the way to the right side)
Resize the width of window in opposite (RTL) direction
Scrollbar starts to behave odd and scrollable content is in the wrong position
I get this situation:
Width of scrollbar's contentItem (aka scrollbar's handle) is wrongly calculated.
Scrollbar's position is also wrongly calculated
The content is not scrolled to the right place (property "x" of scrollable content is wrongly calculated )
What I want is that:
the width of scrollbar's contentItem (aka scrollbar's handle) increases proportionately as the width of the window increases
the content (which was in the position that its right side was completely visible) should stay in that position. And with the expansion of the window, on the left side, the other part of the content that was not visible until then, should start to show up.
The same things are happening if I try to use non-attached QML ScrollIndicator.
This seams to be the bug in QML, and I have reported it, but I need the solution now... If anyone could help, it would be great. Thanks!
import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
Window
{
id: main
width: 400
height: 200
Rectangle
{
id: frame
clip: true
anchors.fill: parent
color: "purple"
Text
{
id: content
text: "ABCDE"
font.pixelSize: 160
x: -hbar.position * width
}
ScrollBar
{
id: hbar
hoverEnabled: true
active: true
policy: ScrollBar.AlwaysOn
visible: size < 1
orientation: Qt.Horizontal
size: frame.width / content.width
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
background: Rectangle
{
color: "black"
}
}
}
}
scrollbar behavior
You should consider using a Flickable instead of setting the position of your text manually:
Flickable {
anchors.fill: parent
contentWidth: content.paintedWidth
boundsBehavior: Flickable.StopAtBounds
ScrollBar.horizontal: ScrollBar {
hoverEnabled: true
active: true
policy: ScrollBar.AlwaysOn
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
background: Rectangle {
color: "black"
}
}
Rectangle {
id: frame
clip: true
anchors.fill: parent
color: "purple"
Text {
id: content
text: "ABCDE"
font.pixelSize: 160
}
}
}
Edit:
If you really need the ScrollBar to be attached to a Rectangle, you can add bounds to your Text position:
x: Math.min(0, Math.max(-hbar.position * width, frame.width - content.width))
with
ScrollBar {
visible: frame.width < content.width
// ...
}

QML ToolButton not resizing

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

qml using Row to align components in the center

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

QML Layout not limiting width of children

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
}

Resources