c++ - QFontMetrics 返回不准确的结果

标签 c++ qt fontmetrics

我的 QTableWidget 中有一个自定义委托(delegate),用于在用户搜索某些内容时突出显示匹配项。不幸的是,矩形位置通常不适合某些字符或短语,或者取决于匹配的数量或前导字符串的大小。我找不到导致此问题的具体原因。这是一个例子:Example .

这是我的绘画例程(尝试解决问题的所有尝试和错误有点困惑):

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);
    }
}

注意:filter_string是要搜索的字符串,find_ci只是对std::string::find<的包装 包括不区分大小写,但在这里并不重要,因为这个测试用例完全是小写的,我使用 std::string 来处理非 qt 内容。

编辑:对于宽度计算,我尝试了 fm.tightBoundingRect().width()fm.boundingRect.width()fm.width() 具有不同但从未正确的结果。

我使用 Qt 5.2

最佳答案

在我的例子中,我通过以下 hack 获得了预期的结果:

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

尚不完全清楚为什么 other overload of boundingRect返回正确的结果,但这可能只是偶然的,因为正如文档所述:

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.

width您建议的方法也会返回更大的结果,但它似乎不正确,因为只有在您需要下一个单词的位置时才应使用它:

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

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

关于c++ - QFontMetrics 返回不准确的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27336001/

相关文章:

c++ - 如何在 Microsoft Visual C++ 2019 中选择较旧的编译器?

c++ - g++ 的 std::list::sort 是否使迭代器无效?

c++ - Qt Creator 没有名为 stackedWidget 的成员

qt - QML ListView 页眉和页脚项目?

python - 保存 Python plasmoid 的配置

java - 右对齐图片上的文字

c++ - 选择从哪个 CRTP 基类派生

pdf - Open Type 字体中的字形宽度

java - 如何使文本字体缩小并匹配 JTextArea 高度?

c++ - 使用 std::for_each 遍历树