Jay
Jay

Reputation: 14461

centering word wrapped kerned text

I'm creating a custom control and wanted to make it generic enough to use any orientation. When I try vertical orientation the kerned text isn't centered. You can see that best with the character 'i' in the attached image. Any suggestions?

centering kerned text

Here's how I'm rendering the text:

  int flags = Qt::AlignJustify | Qt::AlignVCenter | Qt::TextWrapAnywhere;
  painter.drawText( TextArea, flags, text );

painter is a QPainter. This code is in the paintEvent() method.

Upvotes: 2

Views: 839

Answers (2)

Arnold Spence
Arnold Spence

Reputation: 22272

Putting a linefeed after each character might do the trick.

Update:

Also, I think you should remove the Qt::AlignJustify flag. I didn't notice before that you were missing the horizontal centering flag. Try these flags:

int flags = Qt::AlignVCenter | Qt::AlignHCenter | Qt::TextWrapAnywhere;

or

int flags = Qt::AlignCenter | Qt::TextWrapAnywhere;

Upvotes: 1

pnezis
pnezis

Reputation: 12321

I don't think there is a Qt function that achieves what you want. However you could paint it letter by letter. Here is how you could do it:

 QFontMetrics fm = painter.fontMetrics();
 QString t = "Sample";

 // Loop through all letters
 int topX = 5;
 int topY = 5;
 int yOffset = 0;

 for (unsigned i=0; i<t.count(); i++)
 {
   QChar c = t.at(i);
   // Get metrics
   int w = fm.width(c);
   int h = fm.height();

   painter.drawText(topX-w/2, topY-h/2, QString("%1").arg(c));

   topY = topY + h + yOffset;
 }

How it works

  • Get the font metrics in order to calculate the width and height of every letter.
  • topX, topY are the center coordinates of your first letter in painter coordinates
  • yOffset is the vertical distance between the letters
  • For all letters get their width and height.
  • Draw them at the correct position. Since when text is drawn we give its top left position, we give it with respect to its center in order to have it centered
  • Increase topY by the previous letter's height and the y offset
  • TODO: Check that the drawn text is within widget's boundaries...

EDIT

A second approach that draws the text within a given rectangle:

  • Split the initial rectangle into n sub rectangles where n the number of letters in the provided string.
  • Paint each letter to the center of the corresponding sub rectangle
  • The advantage of this method is that the text is drawn within a given bounding rectangle so it can fit vertical controls...

Sample code:

/* Let rect the rectnagle in which we want to draw the vertical text
and t the string we are drawing. rectH is the height of every sub-rectangle */
double rectH = rect.height() / (double) t.count();
for (unsigned i=0; i<t.count(); i++)
{
     QChar c = t.at(i);

     // Draw every char in the corresponding sub rectangle
     painter.drawText(QRect(rect.topLeft().x(),
                rect.topLeft().y() + i*rectH,
                rect.width(),
                rectH),
              Qt::AlignCenter,
              QString("%1").arg(c));

}

Hope it helps...

Upvotes: 3

Related Questions