2014-12-06 119 views
4

如果用戶搜索某些內容,我在我的QTableWidget中有一個自定義代理來高亮匹配。不幸的是,矩形位置往往不適合這發生在某些字符或短語上,或取決於匹配的數量或引導字符串的大小。我無法找到導致此問題的具體內容。這裏有一個例子:ExampleQFontMetrics返回不準確的結果

這是我的油漆例程(位從所有的試驗和錯誤試圖解決這個問題雜亂):

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

+0

您是否嘗試將'painter.device()'傳遞給'QFontMetrics'構造函數? – BartoszKP 2015-08-17 15:30:57

+0

@BartoszKP我沒有,但不幸的是它沒有改變任何東西。但它導致我嘗試使用'QFontMetrics fm(painter-> font());'在任何情況下,哪個(與'fm.width()'而不是另外兩個)一起處理的結果只有1px的常量偏移量!非常感謝我領導這一點,所以如果你想獲得信貸,我會很樂意接受它 – Bowdzone 2015-08-18 16:36:35

回答

2

在我來說,我得到了下面的技巧所期望的結果:

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

這並不完全清楚爲什麼other overload of boundingRect返回正確的結果,但可能只是偶然,因爲正如文檔所述:

此函數返回的邊界矩形比簡單的boundingRect()計算的邊界矩形稍大功能。此功能使用多行文本所需的最大左右字體方向以正確對齊。此外,fontHeight()lineSpacing()用於計算高度,而不是單個字符高度。

width方法你建議也將返回較大的結果,但它似乎不正確的,因爲它應該被用來只有當你需要爲下一個字的位置:

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

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