Vertical Text Orientation in QML - qt

How can i display a text in QML with vertical orientation like below
Text {
id: name13
text: qsTr("John")
}

I got the answer, need to use rotation property and use the angle, in my case it is 270
Text {
id: name13
text: qsTr("John")
rotation : 270
}

Related

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.

shift the textfield edit area

I have a qml based application where I have a search field. The field also has an icon to indicate it is a search box. The problem is that when I type the text it overlaps the icon and I would like to basically constrain the text input area to the text field which does not contain the image.
The qml code is as follows:
TextField {
id: searchBox
font.pixelSize: 18
background: Rectangle {
radius: 6
border.color: "#707070"
border.width: 1
Image {
source: "../images/search.png"
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
}
}
}
The resulting component is rendered as follows:
As you can see the text input area overlaps with the image. Is there a way to ensure that the text input area gets clipped or in this case shifted to the right and that the user cannot add text where the image is rendered?
You can use padding properties
rightPadding: 30
leftPadding: 24

Bounding box of wrapped text

I want to draw a rectangle around a QML Text object that is using word wrapping. TextMetrics seems like it would be ideal, but it does not appear to support wrapped text.
How can I measure how text is laid out in a Text object? Must I match the wrapping logic and manually calculate the offsets using TextMetrics and FontMetrics?
You can use contentWidth and contentHeight:
Text {
text: "..."
wrapMode: Text.Wrap
Rectangle {
border.color: "red"
color: "transparent"
width: parent.contentWidth
height: parent.contentHeight
}
}

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.

Resources