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());
//基本表格单元格矩形
QRect rect_a = option.rect;
//调整矩形以匹配文本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);
//调整矩形以匹配文本高度
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的东西。
编辑:对于宽度计算,我尝试了 我使用Qt 5.2 结果带有以下hack: 不完全清楚 这个函数返回的边界矩形比用简单的 [...] 此外,有时候,你是否传递 I have a custom delegate in my This is my paint routine (a bit messy from all the trial and error trying to fix the issue): Notes: Edit: For the width calculation I tried I use Qt 5.2 In my case I got the desired result with the following hack: It's not entirely clear what the other overload of The bounding rectangle returned by this function is somewhat larger than that calculated by the simpler The [...] Also, sometimes it matters whether you pass the result of 这篇关于QFontMetrics返回不准确的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! fm.tightBoundingRect C>,
fm.boundingRect.width()
和 fm.width()
/ p>
auto initialRect = fm.boundingRect
auto improvedRect = fm.boundingRect(initialRect,0,text);
boundingRect
的其他重载返回正确的结果,但可能只是偶然,因为正如文档所述:
boundingRect()
函数。此函数使用最大左和右字体方位,以便多行文本正确对齐。此外, fontHeight()
和 lineSpacing()
用于计算高度而不是个别字符高度。 p>
width
方法你也会返回更大的结果,但它似乎不正确,因为它应该只有当你需要一个位置为next word:
width()
painter的结果很重要。 device()
至 QFontMetrics
构造函数。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: . 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
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.fm.tightBoundingRect().width()
, fm.boundingRect.width()
and fm.width()
with different but never correct results.auto initialRect = fm.boundingRect(text);
auto improvedRect = fm.boundingRect(initialRect, 0, text);
boundingRect
returns the correct result, but in may be just accidental, because as the documentation states:
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
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.painter.device()
to QFontMetrics
constructor.