Nauroze Hoath
Nauroze Hoath

Reputation: 129

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.

Upvotes: 1

Views: 1612

Answers (1)

dtech
dtech

Reputation: 49289

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.

enter image description here

Upvotes: 3

Related Questions