Search code examples
c++qtqt5qgraphicsrectitem

How to scale text to fit inside a bounding box with QPainter?


I need to draw a label onto a box.

Ideally I'd scale the label with the size of the box, but I'm not sure if there is any built in functionality for this kind of scaling.

At present I'm scaling the object to the height of the bounding box, but I'm not certain how to implement the width scaling because the width of the drawn text depends on the specific order of symbols (due to kerning).

Is there some built in functionality for this kind of scaling?

void total_control_roi_item::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
{
    QGraphicsRectItem::paint(painter, option, widget);
    painter->save();
    const auto rect = boundingRect();
    auto font = painter->font();
    auto height_of_box = rect.height()*0.7;
    font.setPointSizeF(height_of_box);
    painter->setFont(font);
    const auto label = QString("%1").arg(id_);
    painter->drawText(rect, label, Qt::AlignHCenter | Qt::AlignVCenter);
    painter->restore();
}

Solution

  • You can make a text escalation using the information of QFontMetrics.

    #include <QtWidgets>
    
    class RectItem: public QGraphicsRectItem
    {
    public:
        using QGraphicsRectItem::QGraphicsRectItem;
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
        {
            const QString id_ = "Stack Overflow";
            const auto label = QString("%1").arg(id_);
            QGraphicsRectItem::paint(painter, option, widget);
            if(label.isEmpty()) return;
            const auto rect = boundingRect();
            QFontMetrics fm(painter->font());
            qreal sx = rect.width()*1.0/fm.width(id_);
            qreal sy = rect.height()*1.0/fm.height();
            painter->save();
            painter->translate(rect.center());
            painter->scale(sx, sy);
            painter->translate(-rect.center());
            painter->drawText(rect, label, Qt::AlignHCenter | Qt::AlignVCenter);
            painter->restore();
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QGraphicsScene scene;
        QGraphicsView w(&scene);
        scene.addItem(new RectItem(0, 0, 300, 200));
        w.resize(640, 480);
        w.show();
    
        return a.exec();
    }