Find the text width in QFont

2k Views Asked by At

I have two items in my tree model i have small difference in text alignment.Is this caused by the width of the text but i checked the width of text using QFontMetrics::width() but both text are same.

Text1:111601756
Text2:999999996

As from the image you can see there is a slight alignment problem in the second text.

enter image description here

Here is the sample code i tried :-

QFont font("times",24);
QFontMetrics metrics(font);
qDebug() << "Width 1" <<      metrics.width(QString::number(111111111));
qDebug() << "Width 2" << metrics.width(QString::number(999999999));

Output:

Width 1 153

Width 2 153

MyDelegate paint function:-

void LiDefaultTreeDelegate::paint(QPainter *painter, const    
QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem newOption = option;
if(index.data(Qt::DisplayRole).toString() != NULL)
 {

    QString text = index.data(Qt::DisplayRole).toString();

    QFontMetrics fnMetrics(fn);
    newOption.rect = fnMetrics.boundingRect(text);
    //Case 1
    //newOption.rect.setWidth(fnMetrics.width(text));
    //Case 2
    //newOption.rect.setWidth(fnMetrics.width('0') * option.rect.width());
 }
  QStyledItemDelegate::paint(painter, newOption, index);
}

Now the problem is painting happens in the wrong area as from the image you can see the data gets painted on the top of root item. Any clue what I am missing here.

New Output:

enter image description here

2

There are 2 best solutions below

4
On

Here's a partial answer, and partly speculation:

The widths are correct (for that font). The problem appears to be, that QTreeView does not use that width, it uses the bounding rect's width (this is a guess in my part, not 100% certain). To see the difference in width, try this version of your test code:

QFont font("times",24);
QFontMetrics metrics(font);
qDebug() << "Rect 1" << metrics.boundingRect(QString::number(111111111));
qDebug() << "Rect 2" << metrics.boundingRect(QString::number(999999999));

It should show that first rect is less wide. This is because even though char spacing is same, 1 is actually narrower that 9, so there is more empty space at the left and right of the string. And bounding rect excludes this empty space, it reports the smallest rectangle where everything drawn is shown.

So you need to look into the delegate which draws your model items, the problem is there! If everything else fails, you may have to implement your own delegate to do the drawing right.


Suggested fix for the code now shown in the question:

newOption.rect = fnMetrics.boundingRect(text); // existing line
newOption.rect.setWidth(fnMetrics.width(text)); // add width adjustment

Note that you may also need to adjust the alignment for painting, if it is now centered, since you probably want left-justified text there.

Note, this fix assumes the font has same width for all the number characters (I think this holds for most fonts, since otherwise numbers would be hard to read), and numbers have equally many digits. If not, you might try something like this instead, to get equal width for all items:

newOption.rect.setWidth(fnMetrics.width('0') * desiredColumnWidth); // width adjustment
0
On

Here is the answer provided by my friend in other blog.The problem here is the font family for example here the font family is MS Shell Dlg 2 which uses the space available in the text like 1 is more narrower than 9 so it uses that space and thus leads to alignment problem but there are font family that uses fixed width.So the trick here is change the font family that uses fixed width to avoid this problem.

For Example following are some of the families that uses fixed width:-

  1. Times
  2. Courier
  3. Courier new