Important: Please read the Qt Code of Conduct -

[SOLVED] QPainter - drawText same rectangle, different font

  • I would like to paint some text inside a rectangle using drawText(..), but also have different font for some part of the text.
    So far it seems you can only use the same font for the whole rectangle. Is it possible to do this without creating 2 rectangles ? The size of the QRectangle could vary so I would like to avoid 2 rectangles if possible (translation = different text length)

    Output report :

    Code used:
    @ /// --------- Draw Labels (bold) ---------------
    QFont font = painter.font();

    QString name = tr("Name: ");
    QString type = tr("Type: ");
    QString plan = tr("Plan: ");
    QString creator = tr("Creator: ");
    QString description = tr("Description: ");
    int sizeName = painter.fontMetrics().width(name);
    int sizeType = painter.fontMetrics().width(type);
    int sizePlan = painter.fontMetrics().width(plan);
    int sizeCreator = painter.fontMetrics().width(creator);
    int sizeDescription = painter.fontMetrics().width(description);
    QRectF recNameLabel = QRectF(QPointF(0, 0), QPointF(width/2, 200));
    QRectF recTypeLabel = QRectF(QPointF(0, 200), QPointF(width/2, 400));
    QRectF recPlanLabel = QRectF(QPointF(0, 400), QPointF(width/2, 600));
    QRectF recCreatorLabel = QRectF(QPointF(0, 600), QPointF(width/2, 800));
    QRectF recDescriptionLabel = QRectF(QPointF(width/2 - sizeDescription, 0), QPointF(width/2, 200));
    painter.drawText(recNameLabel, Qt::AlignLeft, name);
    painter.drawText(recTypeLabel, Qt::AlignLeft, type);
    painter.drawText(recPlanLabel, Qt::AlignLeft, plan);
    painter.drawText(recCreatorLabel, Qt::AlignLeft, creator);
    painter.drawText(recDescriptionLabel, Qt::AlignLeft, description);
    /// ------------------- Draw content -----------------
    QRectF recName = QRectF(QPointF(sizeName, 0), QPointF(width/2, 200));
    QRectF recType = QRectF(QPointF(sizeType, 200), QPointF(width/2, 400));
    QRectF recPlan = QRectF(QPointF(sizePlan, 400), QPointF(width/2, 600));
    QRectF recCreator = QRectF(QPointF(sizeCreator, 600), QPointF(width/2, 800));
    QRectF recDescription = QRectF(QPointF(width/2, 0), QPointF(width, 800));
    QRectF recSignature = QRectF(QPointF(0, height-200), QPointF(width, height));
    painter.drawText(recName, Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap, workout.getName());
    painter.drawText(recType, Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap, workout.getTypeToString());
    painter.drawText(recPlan, Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap, workout.getPlan());
    painter.drawText(recCreator, Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap, workout.getCreatedBy());
    painter.drawText(recDescription, Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap, workout.getDescription());
    painter.drawText(recSignature, Qt::AlignTop | Qt::AlignRight | Qt::TextWordWrap, tr("Workout created with"));
    // draw QwtPlot
    QwtPlotRenderer renderer;
    renderer.setDiscardFlag(QwtPlotRenderer::DiscardBackground, true);
    renderer.setDiscardFlag(QwtPlotRenderer::DiscardCanvasBackground, true);
    renderer.setDiscardFlag(QwtPlotRenderer::DiscardCanvasFrame, true);
    renderer.render(ui->widget_plot_report, &painter, QRectF(QPointF(0,1000), QPointF(width,height-200)));

  • Moderators

    short answer: no
    Although the calculations shouldn't be that complicated in your case.
    An alternative could be to setup a simple HTML snippet (e.g. table) and set it to a QTextDocument and render it instead. This has the advantage that it takes care of wordwrap automatically.

  • Moderators

    QStaticText supports HTML subset for formatting, so you could do something like this:
    QStaticText text;
    text.setText("<b>Name:</b> Added text after name that is not bold..");
    painter.drawStaticText(yourRectangle.topLeft(), text);
    Note that preparing static text is slower than just using drawText() so you should probably cache the QStaticText somewhere and update only when needed.

  • Thanks for the advices guys.

    QStaticText could work but I would like to use the QRectF approach, some text will require multiple lines and automatic jump line is handy..

    What could work is to create some sort of formula to measure the length used of a QString, so I don't write over it.
    @ QString name = tr("Name");
    int sizeUsed = name.length()*10; //possible to calculate length of the string with current font?@

    I updated the code up here

  • Moderators

    QStaticText supports line wrapping. See my example. You give it a width (from your rectangle) and then a point(also from your rectangle) to draw at. It will wrap text that doesn't fit for you. You can also draw multi-line text in one go so it will take care of proper line spacing etc.

    To measure needed offset for next string you can use
    Just make sure you call that with the right font set first (the one you use for the text you want to skip).

  • Thanks Chris,

    Working perfect with:
    updated the code up here

    Code is a bit long, but does what it needs to do! That's why I love Qt, you can do almost everything with some hacking.

    Have a great day!

Log in to reply