QML TextField will not position text based on cursorPosition - qt

I have created a simple TextField with a long text therein. Every time I run the code the LAST part of the text fields shows. Since I set cursorPosition to 1, shouldn't the FIRST part of the text field show?
TextField {
x: 0
id: inputField
width: 100
text: "Hello World 2! ababaabababababababa"
color: gui.colorRGBString(GUIConstants.EColorElement_TextTitle)
maximumLength: 128
cursorPosition: 1
}

It seems that the property is being evaluated before placing the text so a possible solution is to invoke it in component.OnCompleted:
TextField {
id: inputField
x: 0
width: 100
text: "Hello World 2! ababaabababababababa"
color: gui.colorRGBString(GUIConstants.EColorElement_TextTitle)
maximumLength: 128
Component.onCompleted: inputField.cursorPosition = 1
}

Related

Add hint to QML TextField with maximum length?

I have a QML TextField where the user can input a limited amount of characters. Is there a way to add a simple hint like so? It can be inside the input too (as uneditable text, of course), or next to it.
ColumnLayout {
Label {
text: "Short description"
}
TextField {
Layout.fillWidth: true
maximumLength: 30
}
}

How to check the auto alignment of text when Text contains Arabic words

I have created a Rectangle item with Text item in center which acts as Edit box with Cursor item at the end of the text.
So for Orientation to be taken care by QML, I have modified the Text item as
Text
{
id: text_input
font.bold: true
font.pixelSize: 22
color: "white"
text: view.defaultTextField
elide: Text.ElideLeft
verticalAlignment: Text.AlignVCenter
anchors.fill: parent
maximumLineCount: 1
clip: true
anchors{
rightMargin: 10
leftMargin: (textInputField === "") ? 18 : 12
verticalCenter: parent.verticalCenter
}
}
and Cursor image as
Image
{
id: img_cursor
x: (textInputField !== "") ?
(text_input.x + text_input.contentWidth)) : 12
anchors.verticalCenter: parent.verticalCenter
source: "text_cursor.png"
}
Now if textInputField contains Arabic text, TextItem is auto change the orientation from right to left. and english it is changing to start from Left.
Text appending coming in :
Arabic: Left <--Right
English: Left --> Right
But for Cursor position, how i can make the logic to auto detect and change the x position of the cursor based on the text_input orientation direction (Arabic and English).
Arabic isn't always RtoL. Numbers, for example, are written LtoR (just like in English). Also, foreign words would be written LtoR. Conversely, if you add an Arabic word in an English text, text direction will change somewhere. Might be the middle of the line, might be at either end.
That's why a simple trick like calling QFontMetrics.width() will only work for simple cases.
Try QTextLayout instead. QLineEdit uses this code in it's control to figure out the X position of the cursor:
qreal cursorToX(int cursor) const { return m_textLayout.lineAt(0).cursorToX(cursor); }
I created a function to check the alignment of the text. so on arabic change , the Text orientation will be modified automatically.
function isArabicAlignment() {
if(text_input.horizontalAlignment === Text.AlignRight)
return true;
else
return false;
}
So on Text input modifies , i will check the condition and update the cursor position.
x: (textInputField !== "" && isArabicAlignment()) ?
(text_input.x + text_input.contentWidth)) : //Changing Cursor in reverse.

How do you select a character from text in Qt?

I've uploaded a text file and parsed the content into a text object. Eventually I will be passing each character in the string to a rectangle of its own. I am trying to figure out how to pick a character from the string in qml?
For example:
//Assume the text is already parsed from the file and it is stored in the object below
Text {
id:myText
text: "The quick brown fox jumps over the lazy dog"
visible:false
}
// And now i would like to transfer the first letter into a rectangle
Rectangle{
id: firstRect
width:rectText.width
height:rectText.height
color: "yellow"
Text {
id:rectText
text: // How do I set this as the first character 'T'
font.pixelSize: 14
color: "black"
}
}
How can set the rectangle with the character from myText to rectText ?
Eventually I will be setting each character in a rectangle of its own.
It is close to impossible. At least not by using what little font metrics functionality is provided to QML. There is TextMetrics available since Qt 5.4, but for some reason it didn't report the text size accurately, at least for the fonts that I've been using. It may have to do with this issue. I ended up getting accurate results by appending the 字 character to the queried text, and I don't even want to go into detail how I figured that out.
And then, if that happens to work, you only have the text dimensions, but no way to determine the position of that rectangle, since QML text elements can only give you the cursor position, but not the position of any particular character. If you have a single line of text it could be doable - just calculate the width of the preceding text, but for multi line it is a no-go.
You will probably have to take a very different approach. Maybe implement an adapter that presents strings as list models, and you represent every individual character as a QML element in something like a flow view.
But having a discrete visual item for every character will be huge overhead for long text, so if you are going to have such text, you will also have to handle a model proxy that only displays a particular portion of the text.
I can currently think of no other way to get accurate information about the position and size of text character. The API simply doesn't have that functionality.
There is a simple example that is perfectly applicable for short text:
ApplicationWindow {
id: main
width: 640
height: 480
visible: true
property var charlist: textfield.text.split('')
property int currentChar: 0
Column {
TextField {
width: main.width
id: textfield
text: "example text"
}
Flow {
width: main.width
height: 200
Repeater {
model: charlist
delegate: Rectangle {
Text { id: tt; text: modelData; font.pointSize: 20 }
width: tt.width
height: tt.height
color: "red"
border.color: index === currentChar ? "black" : "red"
MouseArea {
anchors.fill: parent
onClicked: {
currentChar = index
var pos = mapToItem(main.contentItem, 0, 0)
info.text = "rectangle x y w h: " + pos.x + ", " + pos.y + ", " + width + ", " + height
}
}
}
}
}
Text {
id: info
}
}
}
You can enter arbitrary text in the text field, which will be represented by a model view that creates an item for every character. Clicking a character will "select" it and will also give you the rectangle values corresponding to its position in the application window.

Detect text content size in TextField

I'd like to reduce the font size in case user types a long text in a TextField. Is there a way to know how wide the current text is rendered?
As far as I know, it is not possible to do directly. You could, however, cheat by using an invisible item that contains the properties you need:
Text {
id: hiddenText
anchors.fill: tf
text: tf.text
font.pixelSize: tf.font.pixelSize
visible: false
}
TextField {
id: tf
width: 100
height: 60
font.pixelSize: 25
onTextChanged: {
while ((hiddenText.contentWidth > hiddenText.width) || (hiddenText.contentHeight > hiddenText.height)) {
font.pixelSize -= 1
}
}
}
You would have to do the same for scaling up the text, in case the user erases some input. The Text component does not contain borders, so you have to decrease it's width by a few pixels to make it the same size as the TextField as well.
Also, check out TextArea or TextInput. They may fit your need.

QML IntValidator strange behavior for bottom > 0

I have a few IntValidators inside as many TextInputs and they all behave well, except one. The one misbehaving is the only one with its bottom property set to something greater than zero. The problem is easily riproducible with the code below (Qt 5.2.0):
import QtQuick 2.1
Rectangle
{
id: mainwindow
objectName: "mainwindow"
width: 1024
height: 768
TextInput
{
id: testtextinput
objectName: "testtextinput"
text: "170"
font.pixelSize: 36
x: 100
y: 200
width: 200
height: 200
property size range: Qt.size(160, 180)
validator: IntValidator
{
id: rangevalidator
objectName: testtextinput.objectName + "_rangevalidator"
bottom: testtextinput.range.width
top: testtextinput.range.height
Component.onCompleted:
{
console.log("Component.onCompleted objectName: " + objectName + " bottom: " + bottom + " top: " + top)
}
}
onAccepted:
{
text = "accepted"
}
}
Text
{
id: testisacceptable
font.pixelSize: 36
text: testtextinput.acceptableInput
anchors.top: testtextinput.bottom
anchors.left: testtextinput.left
anchors.right: testtextinput.right
height: 200
}
}
The validator's range is set to [160, 180], so, if I want to type 181, I can just type 18 and nothing more. However, if I want to type 159, the TextInput allows me to write the whole number, tells me that the number won't be accepted setting to false the acceptableInput property, but when I press enter, the onAccepted() slot is executed without problems. Any ideas on what's happening here? A bug?
This bug is solved in Qt 5.3.0 as explained here.

Resources