QML - how to overlay a label - qml

I would like to create a progress bar in which the progress is also displayed as text.
Through a blog post, the progress bar was quickly created.
Unfortunately, the progress bar overwrites the text. Is there a way to overlay this?
Item {
id: item
property double maximum: 10
property double value: 50 //mill.value
property double minimum: 0
property bool visibleValue: true
height: parent.height
width: parent.width
Rectangle { id: frame; width: parent.width; height: parent.height; color: "lightgrey"; border.width: 1; radius: 0.5 * height
Label {
anchors.centerIn: parent;
text: item.value + " %";
color: "black";
font.bold: true;
visible: item.visibleValue
}
Rectangle {
visible: item.value > item.minimum
x: 0.1 * frame.height; y: 0.1 * frame.height
height: 0.8 * frame.height
width: Math.max(height, Math.min((item.value - item.minimum) / (item.maximum - item.minimum) * (parent.width - 0.2 * frame.height), parent.width - 0.2 * frame.height)) // clip
color: 'darkgrey'
radius: parent.radius
}
}
}

You need to swap the order of the inner Label and Rectangle.
There are other issues, such as the display of the label being incorrect for your example. You will get "2%" shown, when, in fact, for a range of 0-10 and a value of 2, the calculated percentage should be "20%". I thought I just draw that to your attention, but, I haven't applied the fix, since, I am not sure what you're gunning for.
Item {
id: item
property double maximum: 10
property double value: 2 //mill.value
property double minimum: 0
property bool visibleValue: true
height: parent.height
width: parent.width
Rectangle { id: frame; width: parent.width; height: parent.height; color: "lightgrey"; border.width: 1; radius: 0.5 * height
Rectangle {
visible: item.value > item.minimum
x: 0.1 * frame.height; y: 0.1 * frame.height
height: 0.8 * frame.height
width: Math.max(height, Math.min((item.value - item.minimum) / (item.maximum - item.minimum) * (parent.width - 0.2 * frame.height), parent.width - 0.2 * frame.height)) // clip
color: 'darkgrey'
radius: parent.radius
}
Label {
anchors.centerIn: parent;
text: item.value + " %";
color: "black";
font.bold: true;
visible: item.visibleValue
}
}
}

Related

How do i access the currentIndex from gridview in qml and update it on changed [In QML]

How can I get the currentIndex from the gridView and highlight it and update back the currentIndex once it's changed to another item? [IN QML]. Please let me know what is the solution.
Thank you in advance!
GridView{
id: colorGrid
model: colorModelData
delegate: ItemDelegate{
id: colorcomboDelegate
background: Rectangle {
id: colorRect
anchors.centerIn: parent
width: colorGrid.cellWidth * 0.6
height: colorGrid.cellWidth * 0.6
radius: width/2
color: colorModelData[index]
}
Rectangle {
id:colorSelectedRing
anchors.centerIn: parent
width: colorRect.width * 1.30
height: width
radius: width/2
z:-1
visible: index=== colorGrid.currentIndex? true:false [...ERROR]
Rectangle {
id:colorSelectedBlackRing
anchors.centerIn: parent
width: colorRect.width * 1.13
height: width
radius: width/2
}
}
}
currentIndex: [Need to update the current index]
}

QML Slider : handle and mouse cursor

I created a slider in an item and customized it like in the following code :
Item {
id: item1
x: 0
y: 0
width: 200
height: parent.height
Rectangle {
id: background
anchors.fill: parent;
color:Qt.rgba(0.9,0.9,0.9,1);
}
Slider {
anchors.centerIn: parent
orientation: Qt.Vertical
height: parent.height
style: SliderStyle {
groove: Rectangle {
implicitWidth: 200
implicitHeight: 8
color: "gray"
radius: 8
}
handle: Rectangle {
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
width: 20
height: 20
radius: 6
}
}
}
}
The problem appears when I change the size of the handle to have it wider than high, so I change in the handle :
width: 20
height: 80 //the height is changed instead of width but I think
//it's because it is a vertical slider
And then, when I move the handle, it doesn't stay under the mouse cursor but there is an offset between the two.
How to fix that?
The slider is internally rotated 90 degrees when the orientation is vertical, so you'll need to set the width instead of the height. In other words, always style the handle assuming that the slider is horizontal, and the rest will just work...
... except for the mouse offset bug that you just ran into. It appears that your use case isn't auto-tested. Please submit a bug report at bugreports.qt.io.

QML: Center variable text and image

I need to horizonally center a variable-length text (red box) and an image (yellow box) in a big box (green box). The text shall wrap if it does not fit the box.
Existing code:
Item {
id: bigBox
x: 255
y: 0
width: 800
height: 100
Image {
id: imageBox
source: "image.png"
width: 52
height: 46
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Image.AlignLeft
verticalAlignment: Image.AlignVCenter
fillMode: Image.Pad
}
Text {
id: textBox
anchors.left: symbol.right
anchors.leftMargin: 12
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
text: qsTr("heading text")
font.pixelSize: 36
font.bold: true
horizontalAlignment: Text.AlignCenter
}
}
Update:
Actual running code and a real screenshot showing the problem:
import QtQuick 2.0
Rectangle {
id: mask
x: 0
y: 0
width: 800
height: 430
color: "#FFFFFF"
property int pageState: 0
Rectangle {
x: 0
y: 0
width: 111
height: 100
color: "#0000FF"
}
Item {
id: whitespace
x: 117
y: 0
width: 800-x
height: 100
Row {
anchors.centerIn: parent
Image {
id: symbol
source: "../img/pepper.png"
width: 52
height: 46
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.Pad
}
Text {
id: heading
property var texts: ["Active Blabla","Active Blaaaaaaah Blaaaah ","Active Blabla and Blaaaaaaah Blaaaah"]
anchors.verticalCenter: parent.verticalCenter
color: "#333191"
text: texts[pageState]
font.family: "Liberation Sans"
font.pixelSize: 36
font.bold: true
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
textFormat: Text.PlainText
width: Math.min(150,contentWidth)
}
}
}
Rectangle {
id: stage
x: 0
y: 106
width: parent.width
height: parent.height-y
color: "#FFFF00"
}
Timer {
interval: 1000 // milliseconds
triggeredOnStart: true
repeat: true
running: true
onTriggered: {
pageState=(pageState+1)%3;
}
}
}
The white area top right is the green box in the first picture. The timer simply runs through the three texts, like the real application would do.
Changing the first parameter of Math.min() to 600 does not change anything.
My set of hacks to solve that problem:
Item {
// ...
Text {
function escapeHTML(text)
{
return text.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");
}
function toHTML(imageUrl,text)
{
var textlines=escapeHTML(text).replace(/\r?\n/,"\n").split("\n");
var retval="<center>";
retval=retval+'<table><tr>';
if (imageUrl!="") {
retval=retval+'<td rowspan="'+(textlines.length)+'"><img src="'+imageUrl+'"></td>';
retval=retval+'<td rowspan="'+(textlines.length)+'"> </td>';
}
for (var i=0; i<textlines.length; i++) {
if (i>0) {
retval=retval+"<tr>";
}
retval=retval+'<td>'+textlines[i]+'</td></tr>';
}
retval=retval+'</table>';
retval=retval+"</center>";
return retval;
}
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
textFormat: Text.RichText
text: toHtml("../img/pepper.png",qsTr("heading"))
}
}
<center> centers the text in the available space, but not the image
(it stays left - bug!).
<table> can be centered by <center>, and it can contain the
image.
Wrapping does not work as expected, so the translated text returned
by qsTr() has to contain linebreaks at the right positions.
toHTML() splits at the linebreaks and generates table rows from that.
The image needs a table cell with rowspan, or else the image is placed too high relative to the text.
And finally, verticalAlignment: Text.AlignVCenter places all of that vertically centered -- except for the table borders that I luckily don't need. (If you are bored, add border=1 to the <table> tag.)
And no, the HTML and CSS subset supported by Text.RichText does not support vertical alignment. The rendering engine behaves like ancient browsers, you have to stack hacks and workarounds as if it was still 1996.
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
Item {
id: bigBox
width: 800
height: 100
Row {
anchors.centerIn: parent
Image {
anchors.verticalCenter: parent.verticalCenter
source: "blue.png"
}
Text {
anchors.verticalCenter: parent.verticalCenter
// maximum width of the text
width: Math.min(150, contentWidth)
text: qsTr("heading")
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
}
}

How to change the spacing between items in a Column or Row

I am aligning Items using Column and Row types in QML. Is there any way to give different spacing to each Item. Something along the line of the following:
like:
item1
spacing:10
item2
spacing:20
item3
spacing:40
item4
here is my code:
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle{
id: rect
anchors.fill: parent
Column{
id: column
anchors.centerIn: parent
spacing: 10
Row{
id: row1
anchors.horizontalCenter: parent.horizontalCenter
Rectangle{
width: 300
height: 100
color: "lightgreen"
}
}
Row{
id: row2
anchors.horizontalCenter: parent.horizontalCenter
Rectangle{
width: 100
height: 50
color: "lightblue"
}
}
Row{
id: row3
anchors.horizontalCenter: parent.horizontalCenter
Rectangle{
width: 50
height: 50
color: "green"
}
}
}
}
}
The hacky version with spacer Items
Sometimes I prefer this over ColumnLayout since in some situations I just can't use ColumnLayout (can't explain exactly why though at the moment).
I get it working as follows
Column {
Rectangle {
// ...
}
Item {
width: 1 // dummy value != 0
height: 10
}
Rectangle {
// ...
}
Item {
width: 1 // dummy value != 0
height: 20
}
Rectangle {
// ...
}
}
An Item of width 0 won't work. I suggest putting a Spacer_Col.qml (and Spacer_Row analog) into you Toolbox, looking something like
import QtQuick 2.8
Item {
id: root
property alias spacing: root.height
width: 1 // dummy value different from 0
}
Using ColumnLayout
ColumnLayout {
Rectangle{
// ...
}
Rectangle{
Layout.topMargin: 10
// ...
}
Rectangle{
Layout.topMargin: 20
// ...
}
}
By nesting each rectangle you want to space, as follows;
Row {
spacing: 20
Rectangle { color: "red"; width: 50; height: 50 }
Row {
spacing: 50
Rectangle { color: "green"; width: 20; height: 50 }
Row {
spacing: 100
Rectangle { color: "blue"; width: 50; height: 20 }
}
}
}
Different spacings in a row

QML Row element refuses to work

I know I should be using Row, Column etc. rather than items anchored by ID to make my code simpler and easier to read. But they refuse to work most of the time. For example, in this case:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
ListView {
id: listView
anchors.fill: parent
topMargin: spacing
anchors.leftMargin: spacing
anchors.rightMargin: spacing
clip: true
spacing: 0.5 * pxPermm
model: SqlQueryModel {}
delegate: Rectangle {
id: delegateItem
color: "white"
height: 14 * pxPermm
width: listView.width
clip: true
Row {
id: row
anchors.fill: delegateItem
spacing: pxPermm
Image {
height: row.height
width: height
source: "qrc:/resources/ryba.jpg"
fillMode: Image.PreserveAspectCrop
}
Item {
id: textItem
height: row.height
Label {
anchors.left: textItem.left
anchors.top: textItem.top
text: nazov
font.bold: true
}
Label {
anchors.left: textItem.left
anchors.bottom: textItem.bottom
text: cas
}
}
}
}
}
This shows two Labels on the top of an Image in the delegate of list view. Not two labels to the right of the image, as you would expect. However, this code works:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Layouts 1.1
ListView {
id: listView
anchors.fill: parent
topMargin: spacing
anchors.leftMargin: spacing
anchors.rightMargin: spacing
clip: true
spacing: 0.5 * pxPermm
model: SqlQueryModel {}
delegate: Rectangle {
id: delegateItem
color: "white"
height: 14 * pxPermm
width: listView.width
clip: true
Row {
id: row
anchors.fill: delegateItem
spacing: pxPermm
Image {
height: row.height
width: height
source: "qrc:/resources/ryba.jpg"
fillMode: Image.PreserveAspectCrop
}
Label {
text: nazov
font.bold: true
}
}
}
}
Of course I need to show more than one label in the delegate. What am I missing here?
It turns out that Item has zero width by default. The code works properly after the width is set:
Item {
id: textItem
height: row.height
width: childrenRect.width
// labels etc
}