QFontMetrics返回不准确的结果 [英] QFontMetrics returns inaccurate results

查看:1592
本文介绍了QFontMetrics返回不准确的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果用户搜索某个内容,我的 QTableWidget 中有一个自定义委托。不幸的是,矩形位置通常不太适合这发生在一些字符或短语,或根据匹配的数量或前导字符串的大小。我找不到具体导致这种情况的东西。这里有一个例子:。



这是我的油漆例程(所有的尝试和错误尝试修复该问题有点凌乱):

  void custom_delegate :: paint(QPainter * painter,const QStyleOptionViewItem& option,const QModelIndex& index)const {

const QTableWidget * table_widget = qobject_cast< const QTableWidget *>(qstyleoption_cast< const QStyleOptionViewItemV3 *>(& option) - > widget);
const int cell_width = table_widget-> columnWidth(index.column());

//基本表格单元格矩形
QRect rect_a = option.rect;

//调整矩形以匹配文本begin
QStyle * style;
if(table_widget!= 0){
style = table_widget-> style();
} else {
style = QApplication :: style();
}
const int text_horizo​​ntal_margin = style-> pixelMetric(QStyle :: PM_FocusFrameHMargin,0,table_widget)+ 1;
QRect rect_b = rect_a.adjusted(text_horizo​​ntal_margin,0,-text_horizo​​ntal_margin,0);

//调整矩形以匹配文本高度
QFont cell_font = index.model() - > data(index,Qt :: FontRole).value< QFont>();
cell_font.setPointSize(9);
QFontMetrics fm(cell_font);
const int height = fm.height();

rect_b.setY(rect_a.y()+(rect_a.height()-height)/ 2);
rect_b.setHeight(height);

//显示文本
std :: string cell_text = qstrtostr(fm.elidedText(index.model() - > data(index,Qt :: DisplayRole).toString Qt :: ElideRight,rect_a.width()));
int found_pos = find_ci(cell_text,this-> filter_string,0);
int old_pos = 0;
int found_width = 0;
QRect rect_c = rect_b;

//在cell_text
中查找过滤器字符串的发现while(found_pos!= std :: string :: npos){

std :: string front = cell_text .substr(0,found_pos);
rect_c.setX(rect_b.x()+ fm.tightBoundingRect(QString :: fromStdString(front))。width());
rect_c.setWidth(fm.width(QString :: fromStdString(cell_text.substr(found_pos,this-> filter_string.size())))));
painter-> fillRect(rect_c,Qt :: yellow);
old_pos = found_pos + 1;
found_pos = find_ci(cell_text,this-> filters_string,old_pos);
}
}

注意: filter_string 是搜索的字符串, find_ci 只是一个包装器 std :: string :: find 包括不区分大小写,但在这里不重要,因为这个测试用例是完全小写的,我使用 std :: string 用于非qt的东西。



编辑:对于宽度计算,我尝试了 fm.tightBoundingRect C>, fm.boundingRect.width() fm.width() / p>

我使用Qt 5.2

解决方案

结果带有以下hack:

  auto initialRect = fm.boundingRect 
auto improvedRect = fm.boundingRect(initialRect,0,text);

不完全清楚 boundingRect 的其他重载返回正确的结果,但可能只是偶然,因为正如文档所述:


这个函数返回的边界矩形比用简单的 boundingRect()函数。此函数使用最大左和右字体方位,以便多行文本正确对齐。此外, fontHeight() lineSpacing()用于计算高度而不是个别字符高度。 p>

width 方法你也会返回更大的结果,但它似乎不正确,因为它应该只有当你需要一个位置为next word:


[...] width()


此外,有时候,你是否传递 painter的结果很重要。 device() QFontMetrics 构造函数。


I have a custom delegate in my QTableWidget to hightlight matches if a user searches something. Unfortunately the rectangle position does often not really fit This happens on some characters or phrases or depending on the number of matches or the size of the leading string. I can't find something specific causing this. Here is one example: .

This is my paint routine (a bit messy from all the trial and error trying to fix the issue):

void custom_delegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const{

    const QTableWidget* table_widget = qobject_cast<const QTableWidget*>(qstyleoption_cast<const QStyleOptionViewItemV3*>(&option)->widget);
    const int cell_width = table_widget->columnWidth(index.column());

    // basic table cell rectangle
    QRect rect_a = option.rect;

    // adjust rectangle to match text begin
    QStyle* style;
    if(table_widget != 0){
        style = table_widget->style();
    }else{
        style = QApplication::style();
    }
    const int text_horizontal_margin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, table_widget) + 1;
    QRect rect_b = rect_a.adjusted(text_horizontal_margin, 0, -text_horizontal_margin, 0);

    // adjust rectangle to match text height
    QFont cell_font = index.model()->data(index, Qt::FontRole).value<QFont>();
    cell_font.setPointSize(9);
    QFontMetrics fm(cell_font);
    const int height = fm.height();

    rect_b.setY(rect_a.y() + (rect_a.height() - height)/2);
    rect_b.setHeight(height);

    // displayed text
    std::string cell_text = qstrtostr(fm.elidedText(index.model()->data(index, Qt::DisplayRole).toString(),Qt::ElideRight,rect_a.width()));
    int found_pos = find_ci(cell_text, this->filter_string, 0);
    int old_pos = 0;
    int found_width = 0;
    QRect rect_c = rect_b;

    // find occurence of filter string in cell_text
    while(found_pos != std::string::npos){

        std::string front = cell_text.substr(0, found_pos);
        rect_c.setX(rect_b.x() + fm.tightBoundingRect(QString::fromStdString(front)).width());
        rect_c.setWidth(fm.width(QString::fromStdString(cell_text.substr(found_pos, this->filter_string.size()))));
        painter->fillRect(rect_c, Qt::yellow);
        old_pos = found_pos+1;
        found_pos = find_ci(cell_text, this->filter_string, old_pos);
    }
}

Notes: filter_string is the string searched for, find_ci is just a wrapper for std::string::find including case-insensitivity but not important here as this test case is fully lower-case and I use std::string for non-qt stuff.

Edit: For the width calculation I tried fm.tightBoundingRect().width(), fm.boundingRect.width() and fm.width() with different but never correct results.

I use Qt 5.2

解决方案

In my case I got the desired result with the following hack:

auto initialRect = fm.boundingRect(text);
auto improvedRect = fm.boundingRect(initialRect, 0, text);

It's not entirely clear what the other overload of boundingRect returns the correct result, but in may be just accidental, because as the documentation states:

The bounding rectangle returned by this function is somewhat larger than that calculated by the simpler boundingRect() function. This function uses the maximum left and right font bearings as is necessary for multi-line text to align correctly. Also, fontHeight() and lineSpacing() are used to calculate the height, rather than individual character heights.

The width method you propose also will return larger result, but it does not seem correct, as it should be used only when you need a position for a next word:

[...] width() returns the distance to where the next string should be drawn.

Also, sometimes it matters whether you pass the result of painter.device() to QFontMetrics constructor.

这篇关于QFontMetrics返回不准确的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆