QML - How to correctly set an implicitWith to a GridLayout - qml

I'm using Qml 5.12 and basically trying to set an implicitWidth to a GridLayout.
For that, I have a purple rectangle and set the rectangle's width to the GridLayout.
The red rectangle fit with the GridLayout so I can see the width of my GridLayout.
Here's my code:
Rectangle { anchors.fill: gl; color: "red"; opacity: 0.22 }
Rectangle { id: rect; width: 350; height: 30; color: "purple"; }
GridLayout
{
id: gl
y: 35
implicitWidth: rect.width
columns: 2
Label { text: "This is a test" }
SpinBox { Layout.alignment: Qt.AlignRight }
}
If I run the code, I expect to have my both rectangle with the same width.
But the actual result is that the red rectangle is smaller. So the implicitWidth was not considerate.
Can anybody tell my why ?
Thank's !

The GridLayout compute its own implicitWidth based on its children's implicitWidth. So the value you set gets overwritten by the computed one.
implicitWidth is the width an Item wants to have (and the one it would have if no width is explicitely set). Setting it based on something else than its children or some internal value makes little sense.
Here you want the GridLayout to be the exact size of your Rectangle so just set its width property.

Related

Boundaries issues when rotating Text

I cannot wrap my mind why boundaries of the Text do not change and still are as they were before rotation.
I do simply:
Text {
font.family: "Arial"
color: "#3ba3e4"
font.pixelSize: 12
font.letterSpacing: 2
text: "Vasya was here"
anchors.left: parent.left
rotation: -90
}
When you align with parent it shows gap, I would expect it to be rotated and placed all the way to left side of the parent, but now have gap of half of width of the previously unrotated element.
rotation property holds the rotation of the item in degrees clockwise around its transformOrigin. transformOrigin property holds the origin point around which scale and rotation transform. Nine transform origins are available, as shown in the image below. The default transform origin is Item.Center.
This example rotates an image around its bottom-right corner.
Image {
source: "myimage.png"
transformOrigin: Item.BottomRight
rotation: 45
}
An approach has already been provided in the comments.
Text {
font.family: "Arial"
color: "#3ba3e4"
font.pixelSize: 12
font.letterSpacing: 2
text: "Vasya was here"
transform: Rotation {
origin.x: 25;
origin.y: 25;
angle: -90
}
}

Make rectangle width fill ScrollView

I'm trying to get something in a ScrollView to expand in width to fit the screen. The ScrollView is anchored to the main window.
For example purposes, a Rectangle:
ScrollView {
anchors.fill: parent //mainWindow
Rectangle {
color: "light grey"
height: 1000
width: mainWindow.width
}
}
But when the vertical scrollbar appears, it obscures the Rectangle. I can sort of fix it by using a magic constant:
width: mainWindow.width - 20
But what if somebody has bigger scrollbars on their computer? Also it leaves an ugly empty space on the right when the vertical scrollbar is invisible.
Is there a way to automatically learn what the available space is inside of a ScrollView?
There is no need to explicitly adjust to scroll bar. You can just make it to fill the entire available parent space or so. And if you want specify margins:
ScrollView {
id: scrollView
anchors.fill: parent // mainWindow ?
anchors.centerIn: parent // anchoring as asked
anchors.margins: 20
contentItem:
Rectangle {
id: rectScroll
width: scrollView.viewport.width // set as viewport
height: 1000 // set to what you need
}
}
The original issue was solved mainly due to the width property of Rectangle set to parent.parent.width or scrollView.viewport.width as it is more adequate. The latter is definitely better, as long as the width of precisely viewport of scroll area and not the parent width (which in general not guaranteed to contain only this ScrollView).

Resize rectangle with Text

I want to create a custom drop-down box with text inside. The problem is, when I resize my Rectangle to fold it the Text stays on screen.
Rectangle {
id: dropdown
height: 200
width: 200
color: "red"
Behavior on height {
NumberAnimation {
duration: 1000;
easing.type: Easing.InQuad
}
}
Text {
id: text
anchors.left: parent.left
anchors.top: parent.top
text: "foobar"
}
}
How to solve this?
Ok. I have it thanks to jbache.
I need to put clip:true inside dropdown. According to the documentation of clip:
This property holds whether clipping is enabled. The default clip value is false.
If clipping is enabled, an item will clip its own painting, as well as the painting of its children, to its bounding rectangle.
Hence, by setting the property to true, I can ensure that also the child Text will be correctly hidden on drop-down dismiss.

Fix width label with dynamic font size

Is there a way in cascades to get font size for a given text and fixed width?
I was trying with:
TextField{
autoFit: TextAutoFit.FitToBounds
}
But the text always appear left align. The requirement is to center align text with variable font size label render in fixed rect.
If you want just to center align text, you'd need to use textStyle.textAlign property like that:
textStyle.textAlign: TextAlign.Center
In order to center align text with variable font size label render in fixed rect, you basically need to specify the desired width and height of that rectangle for a Label use textStyle.textAlign property mentioned above and choose the font size via respective textStyle.fontSize Label property. Text aligning will be done by Cascades automatically (of course, if your text couldn't be fit in specified width/height it'd be cut off):
import bb.cascades 1.0
Page {
Container {
layout: DockLayout {}
horizontalAlignment: HorizontalAlignment.Fill
verticalAlignment: VerticalAlignment.Fill
Label {
horizontalAlignment: HorizontalAlignment.Center
verticalAlignment: VerticalAlignment.Center
maxWidth: 300
minWidth: maxWidth
maxHeight: 100
minHeight: maxHeight
multiline: true
text: "Some very very very very very long text here"
textStyle.textAlign: TextAlign.Center
textStyle.fontSize: FontSize.XLarge
}
}
}
I'd recommend this approach for achieving the goal set.
However, if you really want to get absolute values of font being used in a widget, use textStyle.fontSize property for this (TextStyle official documentation).
There are no font metrics in BB10 Cascades at the moment so you won't be able to find out if the font does not fit in the label and resize it.
You can use sort of hack with layoutUpdateHandler to get some rough resizing, but I wouldn't recommend it. If the text changes frequently you will see flickering, but if it's only set once then it might be okay. Change the text set in "onCreationCompleted" to see if the text resizes for you.
Container {
id: root
implicitLayoutAnimationsEnabled: false
background: Color.Cyan
property int width: 500
property string text: ""
property double textSize: 20
layout: DockLayout {
}
attachedObjects: [
LayoutUpdateHandler {
onLayoutFrameChanged: {
if (layoutFrame.width > root.width) {
root.textSize = root.textSize - 1
}
}
}
]
Label {
implicitLayoutAnimationsEnabled: false
maxWidth: root.width
text: root.text
textStyle {
fontSize: FontSize.PointValue
fontSizeValue: root.textSize
}
}
Label {
implicitLayoutAnimationsEnabled: false
text: root.text
opacity: 0
textStyle {
fontSize: FontSize.PointValue
fontSizeValue: root.textSize
}
}
onCreationCompleted: {
root.text = "Hello World AAAAAAAA"
}
}

QML - Control border width and color on any one side of Rectangle element

Currently i had a requirement of drawing a delegate rectangle with the help of ListView control. I was able to draw a series of rectangle either horizontal or vertical within the list view but the problem is with the border of the rectangle. The border width at the intersect point of the adjacent rectangle is of twice the width.
The delegate rectangle is nothing but a Qt Quick Rectangle element.
Is it possible to limit the border width on any one side of the rectangle alone?
Is it possible to change the color on any one side? (Something similar to QLineEdit - Where we can control the border width and color with respect to the sides)
Regards,
Santhosh.
You can make a custom border element like this :
CustomBorder.qml
import QtQuick 1.0
Rectangle
{
property bool commonBorder : true
property int lBorderwidth : 1
property int rBorderwidth : 1
property int tBorderwidth : 1
property int bBorderwidth : 1
property int commonBorderWidth : 1
z : -1
property string borderColor : "white"
color: borderColor
anchors
{
left: parent.left
right: parent.right
top: parent.top
bottom: parent.bottom
topMargin : commonBorder ? -commonBorderWidth : -tBorderwidth
bottomMargin : commonBorder ? -commonBorderWidth : -bBorderwidth
leftMargin : commonBorder ? -commonBorderWidth : -lBorderwidth
rightMargin : commonBorder ? -commonBorderWidth : -rBorderwidth
}
}
main.qml
import QtQuick 1.0
Rectangle
{
width: 500
height: 500
color: "grey"
Rectangle
{
anchors.centerIn: parent
width : 300
height: 300
color: "pink"
CustomBorder
{
commonBorderWidth: 3
borderColor: "red"
}
}
Rectangle
{
anchors.centerIn: parent
width : 200
height: 200
color: "green"
CustomBorder
{
commonBorder: false
lBorderwidth: 10
rBorderwidth: 0
tBorderwidth: 0
bBorderwidth: 0
borderColor: "red"
}
}
Rectangle
{
anchors.centerIn: parent
width : 100
height: 100
color: "yellow"
CustomBorder
{
commonBorder: false
lBorderwidth: 0
rBorderwidth: 0
tBorderwidth: 10
bBorderwidth: 10
borderColor: "blue"
}
}
}
In this example I have used the custom element to make different rectangles which have border on all, one or two sides.
The simplest solution for a ListView is to give your delegate a 1 pixel border and then use a spacing of -1 to get each cell to overlap the other by 1 pixel:
ListView {
spacing: -1
delegate: Rectangle {
height: 40
width: parent.width
border.width: 1
border.color: "black"
z: listView.currentIndex === model.index ? 2 : 1
...
}
...
}
It should work the same for other border widths.
EDIT: Added a nice enhancement from comment below that makes sure the selected item's border is always above all others so that if you change it to indicate selection it's not obscured by its neighbor delegates.
If you're trying to add borders between items in ListView, you should use the given property 'spacing' to establish a common border between each item. Then you could potentially add a background to the ListView to customize border colors.
Example:
ListView {
spacing: 1 // or whatever you want the border to be
}
...But if you really want a specific border you could always use Rectangles to make your own borders:
Item { // this is your 'rectangle'
Rectangle { // the main thing
id: rec
anchors.fill: parent
anchors.leftMargin: 2
anchors.rightMargin: 5
// etc
}
Rectangle { // a border example
anchors.right: rec.right
height: parent.height
width: 5
color: "red"
// etc
}
}
A bit late to answer but the accepted solution draws the border outside the geometry of the rectangle which can be problematic in some cases.
Another way to do this is to do something like:
// CustomBorderRect.qml
import QtQuick 2.12
Item
{
property alias color: innerRect.color
property alias borderColor : borderRect.color
property int borderWidth: 0
property int lBorderwidth : borderWidth
property int rBorderwidth : borderWidth
property int tBorderwidth : borderWidth
property int bBorderwidth : borderWidth
Rectangle
{
id: borderRect
anchors.fill: parent
Rectangle
{
id: innerRect
anchors {
fill: parent
leftMargin: lBorderwidth
rightMargin: rBorderwidth
topMargin: tBorderwidth
bottomMargin: bBorderwidth
}
}
}
}
This can then be used like this:
CustomBorderRect
{
width : 50
height: 30
color: "lightseagreen"
lBorderwidth: 0
rBorderwidth: 5
tBorderwidth: 5
bBorderwidth: 0
borderColor: "lightyellow"
}
This way the border is drawn with the given geometry.