How can I wrap text in QGraphicsItem?
Asked Answered
B

2

6

1) How can I wrap text in a QGraphicsTextItem to fit a fixed rectangle, with width and height ?

Right now I am experimenting with creating a text, getting its bounding rectangle, and resizing it to fit the box - but I can't get wrapping.

class TTT: public QGraphicsTextItem {
    TTT() {
    {
        setPlainText("abcd");
        qreal x = m_itemSize.width()/boundingRect().width();
        qreal y = m_itemSize.height()/boundingRect().height();
        scale(x, y);
    }
    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
        // experiment with clip regions
        // text gets covered by hole in clip
        QRegion r0(boundingRect().toRect());
        QRegion r1(QRect(5, 5, 10, 10), QRegion::Ellipse);
        QRegion r2 = r0.subtracted(r1);
        painter->setClipRegion(r2);
        painter->setBrush(Qt::yellow);
        painter->drawRect(boundingRect());
        QGraphicsTextItem::paint(painter, option, widget);
    }
}

What makes wrapping happen, how can I trigger it ?

Right now, as I keep typing, the box is automatically expanding.

2) Is it possible to wrap the text in a QGraphicsItem / QGraphicTextItem subclass in a shape that is not a rectangle ? enter image description here

(Something like in the image above)
I tried to use clipRegion, see code above, but I guess it is not the right way to go, clipping cuts the text but did not wrap.

Maybe it would... If I could figure out how to wrap text in the first place ?

Qt 4.8

Brae answered 17/6, 2015 at 14:53 Comment(0)
P
5

You did not specify Qt version but try:

void QGraphicsTextItem::setTextWidth(qreal width)

Sets the preferred width for the item's text. If the actual text is wider than >the specified width then it will be broken into multiple lines.

If width is set to -1 then the text will not be broken into multiple lines >unless it is enforced through an explicit line break or a new paragraph.

The default value is -1.

Phreno answered 17/6, 2015 at 15:7 Comment(0)
F
3

In answer to 1) I'd opt not to use the QGraphicsTextItem, but draw the text directly in your QGraphicsItem's paint function using the drawText overloaded function, which takes a QTextOption parameter.

Using this, you can set the WrapMode, for example, with a call to

QTextOption::setWrapMode(QTextOption:: WordWrap)

As for 2) with a non-rectangular shape, I don't think Qt will do this for you.

Doing it yourself you can use QFontMetrics, to work out just how much text would fit in each line, depending upon where it lies within its bounding item.

Alternatively, you could adapt the concept of a text-to-path method.

Flavine answered 17/6, 2015 at 15:5 Comment(6)
I have considered this option for a number of reasons, but will I not lose text editing capabilities ? I still want the text to be editable once placed on the canvas - which I can do now by controlling setTextInteractionFlagsBrae
Also, I have seen this question about using QFontMetrics and it seemed like a great idea - except I don't know how to wrap without adding \n in text - which would be bad because the text could change later, either in content or in size... This is hard !Brae
Will I lose text editing capabilities - in simple terms, yes. However, I'd create my own GraphicsTextItem to do the drawing and allow for editing. Or, you could, when the item is selected, display a QGraphicsTextItem ready to edit and when finished, transfer the info to your own class, which draws it as you want it to.Flavine
This is hard - no one said it would be easy! Rather than adding escaped end of line characters, I'd go with drawing each character separately, as is done with the text-to-path. This will give you the flexibility you need and you'll spend less time trying to fight where to dynamically place the /n character.Flavine
I was just considering - adding a QGraphicsTextItem member object inside a QGraphicsItem subclass perhaps.. or keep the current inheritance but draw the text inside paint instead of calling the QGraphicsTextItem::paint... Thank you for the suggestions, I have some more experiments to do now :-)Brae
I will accept the other answer - setTextWidth is the literal answer to my first question - even though I may have to complicate the implementation to do exactly what i want. (Though your answer gives me a lot more useful information and points me in a better direction)Brae

© 2022 - 2024 — McMap. All rights reserved.