QML Slider value is not updating visually - qt

I am trying to create a Slider in QML. The slider's maximumValue property can change depending on certain states in my application. When the maximumValue property changes I would like to "reset" my slider so that its value property is at the maximumValue. The problem what I am encountering is that when I change the maximumValue property, my value property changes to the right property, but visually it stays at the previous maximumValue property until I don't click on the handle for example.
Here is a simple dummy code, which reproduces this issue:
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property int maxVal: 1
Item {
width: 20
height: 200
Slider {
anchors.fill: parent
orientation: Qt.Vertical
maximumValue: maxVal
minimumValue: 0
value: 1
stepSize: 1.0
style: SliderStyle {
groove: Rectangle {
width: control.height
height: control.width
color: "red"
}
handle: Rectangle {
width: 20
height: 20
color: "green"
Text {
anchors.centerIn: parent
text: control.value
}
}
}
onMaximumValueChanged: value = maximumValue
}
}
Button {
anchors.right: parent.right
text: "Press Me"
onClicked: maxVal = 100
}
}
Below you can see some screenshots of certain stages.
When the application opens:
When I press the "Press Me" button, which sets the maximumValue to 100 from 1. As you can see the value did change from 1 to 100, but visually it stayed at the 1 position:
Finally when I click on the handler of the slider (green rectangle), then it updates and switches value to 1 from 100.
Here is the same thing as a gif:
Anybody encountered this issue before?

It looks like QTBUG-63354, which will be fixed in Qt 5.9.3.

Related

Why does property binding change in QML not propagate immediately

when applying property bindings in QML I have encountered one problem. When we have a parent component (Window) and a child (Rectangle), which has some properties bind to parent's (width, height, or anchors.fill: parent), when I change parents properties in JS code, and if I want to read the values of the child's properties (that are bound to parent's) in the same JS code, it shows the old values (not updated). It looks like that the change of parents properties hasn't been propagated to child's. Here is the example of this problem:
Window {
id:myWindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle{
id:customRec
width:parent.width
height: parent.height
color: "blue"
}
Button{
id:myBtn
onClicked: {
myWindow.width = 800
myWindow.height = 600
console.log(customRec.width)
console.log(customRec.height)
}
}}
After clicking on the button, it shows:
qml: 640
qml: 480
instead of 800 and 600, new values. Although the rectangle has been scaled well. After clicking again it will show updated values (800 and 600). Can someone please explain what is happening here and how can binding property change be propagated immediately to bound properties. I am using Qt 5.12.2 with msvc2017_64 compiler.
You are printing the properties before they got updated. With the below code you can find that onWidthChanged signal comes after the console log. onWidthChanged signal comes after updating the width.
import QtQuick 2.10
import QtQuick.Window 2.10
import QtQuick.Controls 2.2
Window {
id:myWindow
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle{
id:customRec
width: parent.width
height: parent.height
color: "blue"
onWidthChanged: console.log("***********")
}
Button{
id:myBtn
width: 100
height: 100
onClicked: {
myWindow.width = myWindow.width +50
myWindow.height = myWindow.height +50
console.log("--------------------------")
console.log("window width" + myWindow.width)
console.log("window height" + myWindow.height)
console.log("customrect width" + customRec.width)
console.log("customrect height" + customRec.height)
}
}
}

QML ComboBox Popup Issue

I have used so many combo boxes recently but there is an issue in the popup of a particular ComboBox which I am not able to find the exact problem following is the code:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ComboBox{
id:comboNum
width:parent.width * 0.30
height:parent.height * 0.15
model: ["12","23","78","23","45","70"]
currentIndex: 0
popup: Popup{
id:popup
y: comboNum.height - 1
width: comboNum.width
height: comboNum.height * 2
padding: 1
contentItem: ListView {
id: listview
implicitHeight: popup.height
clip: true
model:comboNum.delegateModel
currentIndex: comboNum.highlightedIndex
interactive: true
highlightMoveDuration: 0
boundsBehavior: ListView.StopAtBounds
ScrollBar.vertical:ScrollBar {}
}
}
}
}
The popup doesn't show up all the elements and i am using QT 5.9.1.
Looking at the customisation docs, I can see that it sets a model conditionally, based on whether or not the popup is visible. Doing the same for your snippet makes it work for me:
model: popup.visible ? comboNum.delegateModel : null
However, the Default style implementation of ComboBox doesn't do that, so I'm not sure why it's necessary in your case.

Qt/QML: how to find TextInput maximum width based on validator

Doing my first steps in QML, so this might be obvious...
When using a TextInput with a simple validator (say an IntValidator), is there a way to know the maximum width that TextInput field will take?
As an example, if I create a IntValidator for a number from 0 to 999, I would like to find the width required to display that 999 (or whichever will be the widest, based on the font etc...).
I am trying to wrap that textinput into an item which will have a fixed size, just the right size for the worst case input, nothing less, nothing more?
Thanks.
Use TextMetrics:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
TextMetrics {
id: textMetrics
font: textField.font
text: "999"
}
TextField {
id: textField
width: textMetrics.width + leftPadding + rightPadding
validator: IntValidator {
bottom: 0
top: 999
}
}
}

QML: Resize CheckBox

I have ListView with my own delegate.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
ItemDelegate
{
height: 40
Row
{
spacing: 10
anchors.verticalCenter: parent.verticalCenter
CheckBox
{
}
}
}
The problem is that check boxes does not resize despite ItemDelegate's height.
I get this for height = 40:
I get this for height = 10:
I've tried playing with CheckBox'es width and height values - did not help.
Is it possible to make it smaller at all, without customizing it?
You can, in theory, increase the size of the indicator, but it won't increase the size of the checkmark image:
CheckBox {
text: "CheckBox"
anchors.centerIn: parent
checked: true
indicator.width: 64
indicator.height: 64
}
There are a couple of reasons why the image is not scaled. First of all, the checkmark would be blurry if it was upscaled. And more importantly, to retain best possible performance. Instead of calculating all the sizes relative to each other and that way creating huge amounts of bindings like Qt Quick Controls 1 did, Qt Quick Controls 2 bases its scalability instead on the automatic high-DPI scaling system introduced in Qt 5.6. You get simply a different #Nx image when running with scale factor N.
I'm afraid you need to customize your checkbox to get a different size.
Example:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQml 2.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Component {
id: contactDelegate
ItemDelegate
{
id: item
width: 40
height: 40
CheckBox
{
id: control
text: name
indicator: Rectangle {
implicitWidth: item.width
implicitHeight: item.height
x: control.leftPadding
y: parent.height / 2 - height / 2
border.color: control.down ? "#dark" : "#grey"
Rectangle {
width: 25
height: 25
x: 7
y: 7
color: control.down ? "#dark" : "#grey"
visible: control.checked
}
}
}
}
}
ListView {
width: 180;
height: 200;
spacing: 10
model: ContactModel {}
delegate: contactDelegate
}
}
By the way, the spacing property should be set in your ListView, not the delegate. Otherwise, it has no effect.

How I can dropdown options when I check on checkbox?

I have one Checkbox with onCheckedChanged handler and what I want is, when the Checkbox is checked, dropdown a menu with several texts and text fields. I have the following code:
CheckBox {
id: box
onCheckedChanged: {
// TODO here to dropdown a menu with settings
}
}
I have texts and text fields like the following:
Component {
id: label
Text {
color: "red"
antialiasing: true
smooth: true
}
}
I'm a newbie in QML so please be patient.
You didn't really say where this menu is located, if it's floating or if it is to just appear maybe displacing other elements on the view. Anyway, to anwser your question, you can achieve what you're asking by setting the height of your 'menu' to zero then, when the CheckBox is checked, setting it to however tall you want it to be. To make the menu grow smoothing you can use a NumberAnimation.
You can change your onCheckedChanged() slot to look like this:
onCheckedChanged: {
menu.height = checked ? 100 : 0
}
and add the following, as a child of your menu element:
Behavior on height { NumberAnimation {...} }
to make the menu's height grow from 0 to 100 over a period of time to make it grow smoothly.
Another approach, which I'd prefer, is to use States with a Transition (instead of a Behavior).
Here is an example of a 'menu' which, when the CheckBox is checked, will slide out from beneath the CheckBox:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
ApplicationWindow {
title: qsTr("Hello World")
width: 640
height: 480
visible: true
Rectangle {
id: checkboxContainer
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: 100
color: "pink"
CheckBox {
id: menuCheckBox
anchors.centerIn: parent
text: qsTr("Click Me")
}
}
Rectangle {
id: menu
anchors.top: checkboxContainer.bottom
anchors.left: parent.left
anchors.right: parent.right
height: 0 //This is the default value when the 'default' state is active. That is whenever we're not in the "openState"
clip: true // this hurts rendering performance a bit but is required to make sure child elements don't exceed the bounderies of this object (so when height is zero you don't see the text)
color: "lightblue"
states: [
State {
name: "openState"
when: menuCheckBox.checked // This state is only active when the check box is checked. When you uncheck the check box we move to the 'default' state (which sets the menu's hight back to zero)
PropertyChanges {
target: menu
height: 100
}
}
]
transitions: Transition {
NumberAnimation {
property: "height"
duration: 350 //This means when the height property is changed it will take 350ms to move from what its at to what your changing it to (i.e. 0 to 100 or 100 to 0).
easing.type: Easing.InOutQuad
}
}
Text {
anchors.centerIn: parent
color: "red"
antialiasing: true
smooth: true
text: qsTr("HELLO")
}
}
}
I hope this answers your question.

Resources