簡體   English   中英

QFontMetrics 返回不准確的結果

[英]QFontMetrics returns inaccurate results

如果用戶搜索某些內容,我的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());

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

尚不完全清楚為什么boundingRect的其他重載會返回正確的結果,但這可能只是偶然的,因為正如文檔所述:

此函數返回的邊界矩形比更簡單的boundingRect()函數計算的要大一些。 此函數使用最大左右字體方位角,這是多行文本正確對齊所必需的。 此外, fontHeight()lineSpacing()用於計算高度,而不是單個字符的高度。

您提出的width方法也將返回更大的結果,但它似乎不正確,因為它應該只在您需要下一個單詞的位置時使用:

[...] width()返回到應該繪制下一個字符串的距離。

此外,有時是否將painter.device()的結果傳遞給QFontMetrics構造函數也很重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM