I have a QML TextField
and want to limit the length to 16 characters.
TextField {
id: myTextField
maximumLength: 16
}
Say I enter a multibyte-character like "😊" at the end of a 15 character long string, the emoji gets trimmed and results as �, which is one byte (0x3f in this case). I'm not sure where the 0x3f comes from, because internally the QString
works with UTF-16, so this might be the result of some back and forth conversion between UTF-8 and UTF-16.
The only way I see right now to avoid this trimming of multibyte-characters is to implement my own QValidator
where I then need to check the length of my string with a Unicode aware library like ICU.
My Question now: Is there any other easier way to avoid the trimming, that I'm missing here?
First, let's look at the 😊 emoji:
import QtQuick
import QtQuick.Controls
Page {
Column {
Text { text: "😊" } // 😊
Text { text: "\u{1f60a}" } // 😊
Text { text: "\u{d83d}\u{de0a}" } // 😊
Text { text: "\u{d83d}" } // �
Text { text: "\u{de0a}" } // �
Text { text: "�" } // �
Text { text: "\u{fffd}" } // �
}
}
It is a codepoint character \u{1f60a} which is made up of \u{d83d} and \u{de0a}. Because you set maximumLength to 16 when you paste the emoji you are only getting one of the characters, i.e. \u{d83d} which Qt recognizes as not a character so it replaces it with \u{fffd} which is a placeholder character for "I don't know".
If you want to limit your input to 16 "characters" but want to eliminate that "I don't know" character you can use RegularExpressionValidator.
maximumLength: 16
validator: RegularExpressionValidator {
regularExpression: /[^�]{0,16}/u
}
Alternatively, if you want to limit yourself to 16 codepoint characters, you can do the following:
validator: RegularExpressionValidator {
regularExpression: /.{0,16}/u
}
Here's a fully working example of the former:
import QtQuick
import QtQuick.Controls
Page {
TextField {
id: myTextField
anchors.centerIn: parent
width: parent.width / 2
text: "😊😊😊😊😊😊😊😊"
maximumLength: 16
validator: RegularExpressionValidator {
regularExpression: /[^�]{0,16}/u
}
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
y: parent.height * 3 / 4
text: myTextField.length
}
}
You can Try it Online!