How to switch focus automatically when max length reached in QML TextField? - qml

In order to do that, I understand I need to use some if condition like the one below. But it looks like I did a mistake!
Is the problem in the if condition or in the position, where should I include it?
Grid {
x: 5
y: 3
rows: 5
columns: 20
spacing: 10
Repeater {
id: rpt
model: 50
TextField {
width: 28
height: 50
color: "green"
text:{ "0000";
if(rpt.itemAt(index).text.length ==4)nextItemInFocusChain().forceActiveFocus()
}
font.pixelSize: 12
Keys.onEnterPressed: nextItemInFocusChain().forceActiveFocus()
validator: IntValidator {
bottom: -256
top: 256
}
}
}
}

You want to react when the text changes inside the TextInput, so in the body of the textChanged signal handler:
TextField {
width: 28
height: 50
color: "green"
onTextChanged: {
if (text.length === 4) {
nextItemInFocusChain().forceActiveFocus()
}
}
}
See more on JavaScript Expressions in QML Documents.

Related

How to use QML Repeater for page indicator?

Below is part of my code. It's working fine, however I spent a lot of time trying to solve it with Repeater to be more elegant and flexible, but couldn't.
Could you please suggest a solution to me? The areaMachine is in an other qml file.
Row {
id: pageIndicatorBoxes
anchors.centerIn: pageIndicatorLine
spacing: 5
Rectangle {
id: pageIndicatorBox1
width: 10
height: 10
color: areaMachine.page == 1 ? "#e5e5e5" : "#404040"
}
Rectangle {
id: pageIndicatorBox2
width: 10
height: 10
color: areaMachine.page == 2 ? "#e5e5e5" : "#404040"
}
Rectangle {
id: pageIndicatorBox3
width: 10
height: 10
color: areaMachine.page == 3 ? "#e5e5e5" : "#404040"
}
Rectangle {
id: pageIndicatorBox4
width: 10
height: 10
color: areaMachine.page == 4 ? "#e5e5e5" : "#404040"
}
}
Looks like you haven't look into the documentation about Repeater and its main delegate property. There you can find code examples that fits your problem, so you can combine it and have something like:
Row {
id: pageIndicatorBoxes
anchors.centerIn: pageIndicatorLine
spacing: 5
Repeater {
model: 4
Rectangle {
id: pageIndicatorBox1
width: 10
height: 10
color: (areaMachine.page === (index + 1)) ? "#e5e5e5" : "#404040"
}
}
}

Unable to position custom styled Tumbler

I am trying to give a Tumbler my own style. I declare the Tumbler like this:
Tumbler {
style: MyTumblerStyle {}
height: UIConstants.smallFontSize * 10
width: UIConstants.smallFontSize * 3
TumblerColumn {
model: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
}
}
where MyTymblerStyle is defined like this:
TumblerStyle {
id: root
visibleItemCount: 5
background: Rectangle {}
foreground: Item {}
frame: Item {}
highlight: Item {}
delegate: Item {
id: delRoot
implicitHeight: (control.height) / root.visibleItemCount
Item {
anchors.fill: parent
Text {
text: styleData.value
font.pixelSize: UIConstants.smallFontSize
font.family: UIConstants.robotoregular
anchors.centerIn: parent
scale: 1.0 + Math.max(0, 1 - Math.abs(styleData.displacement)) * 0.6
color: styleData.current?UIConstants.color:"black"
opacity: 1 - Math.abs(styleData.displacement/(root.visibleItemCount-3))
}
}
}
}
I use it in a Row like this:
Row {
MyTumbler {}
StandardText {
color: UIConstants.color
text: "Uhr"
}
}
Now, the result looks like this:
As you can see, the "Uhr" text center is aligned to the top of the Tumbler. Also the Row does not seem to recognize the real width of the Tumbler.
Why? It does work when I do not use MyTumblerStyle.
The problem isn't your style, it's the width assignment.
It helps to break out the Rectangles at a time like this:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Extras 1.3
ApplicationWindow {
title: qsTr("Hello World")
width: 300
height: 600
visible: true
Column {
anchors.centerIn: parent
Tumbler {
id: tumbler
width: 30
TumblerColumn {
model: 25
}
Component.onCompleted: print(width, height, implicitWidth, implicitHeight)
}
Rectangle {
width: tumbler.implicitWidth
height: tumbler.implicitHeight
color: "transparent"
border.color: "blue"
Text {
text: "Tumbler implicit size"
anchors.fill: parent
wrapMode: Text.Wrap
}
}
Rectangle {
width: tumbler.width
height: tumbler.height
color: "transparent"
border.color: "blue"
Text {
text: "The size you gave"
anchors.fill: parent
wrapMode: Text.Wrap
}
}
}
}
(I don't have access to UIConstants, so I guess the width you set)
The implicitWidth of Tumbler is calculated based on the width of each individual TumblerColumn. This allows you to set individual widths for columns, something that is necessary for scenarios where some are wider than others, for example:
So, you should also set the width of your column, or, preferably, only set the width of your column, and not the entire Tumbler:
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Extras 1.3
ApplicationWindow {
width: 300
height: 600
visible: true
Row {
anchors.centerIn: parent
Tumbler {
id: tumbler
TumblerColumn {
model: 25
width: 30
}
}
Text {
text: "Uhr"
}
}
}
This also explains why the Text is weirdly positioned; the Row sees 30 pixels, but the column still has its original (much wider) width.

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 nested row/repeater in a column/repeater

I am trying to create two rows of rectangles using a row/repeater within a column/repeater. The results I am seeing are that the rows of rectangles are stacked on top of each other. I expected to see a blue row of rectangles with a green row of rectangles beneath the blue row. It seems like this should be possible. Any ideas on what I am doing wrong?
I think a code example will help illustrate what I am trying to accomplish.
Here is my main.qml
import QtQuick 2.2
Rectangle {
visible: true
width: 640
height: 480
color: 'black'
border.color: 'white'
RectRow {
id: rectRow
startX: 10
startY: 10
rectVals: [{count: 4, color: 'blue'}, {count: 2, color: 'green'}]
}
}
Here is my RectRow.qml
import QtQuick 2.2
Item {
property var rectVals
property alias startX: rectCol.x
property alias startY: rectCol.y
property string rectBorderColor: '#ffffff'
Column {
id: rectCol
Repeater {
id: repeater
model: rectVals
Item {
height: 50
Row {
property string rectColor: modelData.color
Repeater {
model: modelData.count
Rectangle {
width: 100
height: 50
color: parent.rectColor
border.color: rectBorderColor
}
}
}
}
}
}
}
As in QML Form layout (GridLayout) troubles, you need to give the Item a width:
import QtQuick 2.2
Item {
property var rectVals
property alias startX: rectCol.x
property alias startY: rectCol.y
property string rectBorderColor: '#ffffff'
Column {
id: rectCol
Repeater {
id: repeater
model: rectVals
Item {
width: row.width
height: 50
Row {
id: row
property string rectColor: modelData.color
Repeater {
model: modelData.count
Rectangle {
width: 100
height: 50
color: parent.rectColor
border.color: rectBorderColor
}
}
}
}
}
}
}
Or just remove it altogether; it doesn't seem to be necessary.

Using InputMask in QML

I have a small display window, that should hold an InputMask like "0000.00". When clicking on the Number-Buttons from 0 to 9, the display should show the respective numbers, for example: 0345.89
Here is my code:
TextInput {
id: displayNumbers6Text
cursorVisible: true
focus: true
validator: RegExpValidator {
regExp: /[0-9]+/
}
inputMask: "0000.00"
maximumLength: 7
}
And for the Buttons:
Button {
width: parent.width*0.3
height: parent.height*0.15
buttonColor: "#000000"
MouseArea {
anchors.fill: parent
onClicked: {
displayNumbers6Text.text = "1"
}
}
}
But it doesn't function. What am I doing wrong?
When you assign text property, you reset this value to "1".
If what you are trying is to insert a value when clicking on a button, you can try this :
import QtQuick 2.0
Rectangle {
width: 360
height: 200
TextInput {
id: displayNumbers6Text
width: parent.width
height: parent.height * 0.5
cursorVisible: true
focus: true
validator: DoubleValidator {
}
inputMask: "0000.00"
maximumLength: 7
function appendNum(num) {
var dotPos = text.indexOf(".");
if (dotPos == 4)
text += num;
else
text = text.substr(0, dotPos) + num + text.substr(dotPos);
}
}
Rectangle {
width: parent.width*0.3
height: parent.height*0.15
anchors.top: displayNumbers6Text.bottom
color: "black"
MouseArea {
anchors.fill: parent
onClicked: {
console.log(displayNumbers6Text.text);
displayNumbers6Text.appendNum("1");
}
}
}
}
You can use DoubleValidator instead of a general RegexValidator, it will be more readable.
I add an appendNum function to TextInput to insert a value at the end of the text string. Note that the dot character is always in the string, beacause of the inputMask you set