Why does property binding change in QML not propagate immediately - qt

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

Related

QML Scroll View does not allow scrolling of its content

I need to create components dynamically add added to an area of the screen that, of course, needs to be scrollable. I found out that no matter how many of components I added with the scroll bar as its parent, the scroll bars would not appear and the element would not be scrollable.
I did a little fiddling and I think I came up with a minum working example of what I am talking about:
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")
ScrollView {
width: 200
height: 200
clip: true
Label {
text: "ABC"
font.pixelSize: 224
}
// Rectangle {
// color: "#ff0000"
// width: 100
// height: 100
// }
}
}
This is a modified version of the example used int he official documentation. However when I uncomment the square the screen is no longer scrollable (scroll bars never appear).
If I remove the label and leave the rectangle (making it larger so that there is something to scroll to) it still doesn't work.
I am using Qt 5.10.
So the code below worked for me. I defined a rectangle as a backgroud to get border lines to a scrollable table that I need to create.
Rectangle {
id: tableBackground
color: "#ffffff"
border.width: 2
border.color: "#EDEDEE"
radius: 4
anchors.top: tableHeader.bottom
anchors.left: tableHeader.left
width: vmTableWidth
height: vmTableHeight - tableHeader.height
ScrollView {
id: tableArea
anchors.fill: parent
clip: true
ListView {
id: patientListView
anchors.fill: parent
model: patientList
delegate: VMPatientEntry {
onFetchReport: {
// This is a signal emitted by my VMPatientEntry.
}
}
onCurrentIndexChanged: {
// Do stuff when the current index changes.
}
}
}
}
So I hope this answer allows someone to fix their problem as well.

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 Slider value is not updating visually

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.

QML TextArea strange padding

I have a TextArea. If I set padding constantly padding working normally.
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
TextArea{
font.pixelSize: 20
anchors.fill: parent
wrapMode: TextArea.Wrap
leftPadding: 100 //*parent.width/640
rightPadding: 100 //*parent.width/640
}
}
If I uncomment lines above then I have strange behavior.
What am I doing wrong?
Screenshot
It seems to be a bug, probably some updates are missing, when setting up the width of the contentItem of the ApplicationWindow, so the line lengths are not calculated properly.
If you write:
leftPadding: {
console.log(parent, parent.width)
return 100 * parent.width/640
}
You can see, that the parent.width is initially set to 0 and then changes to 640. When this change happens, there must be something going wrong with the signals.
A resize of the window will update the line lengths, so the proper layout is restored. You might try to file a bugreport on http://bugreports.qt.io to have it fixed.
Other than that, you may give an ID to your ApplicationWindow and use this instead of parent
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
id: win
visible: true
width: 640
height: 480
title: qsTr("Hello World")
TextArea{
font.pixelSize: 20
anchors.fill: parent
wrapMode: TextArea.Wrap
leftPadding: 100 * win.width/640
rightPadding: 100 * win.width/640
}
}

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.

Resources