【发布时间】:2015-05-29 03:56:26
【问题描述】:
首先让我解释一下我想要实现的目标:
在您的浏览器中,按 Ctrl + f 并输入“q”。该操作的结果是我想要实现的。看起来这应该是一个已解决的问题,但尽管我花了很多时间研究、阅读文档并在 Qt IRC 中四处询问,但我仍然陷入困境。也许这里有人可以帮我一把。
以下 Qt 类是我目前正在处理的内容,以防您想复习一下:
Qt::DisplayRole
QModelIndex::data
QAbstractItemView::setDelegate
QTextEdit::setExtraSelections (only as a reference)
QAbstractDocumentLayout::Selection
QTextDocument::drawContents
QStyledItemDelegate::paint
QStyleOptionViewItem
@987654329 @
QTableView
QAbstractItemModel::match
Learn to Model/View Program with Qt
所以现在,让我解释一下我是如何设置的,以及我的研究结果和与 Qt IRC 的互动让我相信我应该做什么。
我正在使用 QStandardItemModel 和 QTableView。附加到 QStandardItemModel 的每一行都有几列。正如我们所知,这些列中的每一列都在 QStandardItemModel 中表示为 QModelIndex。我们可以通过访问它的数据(Qt::DisplayRole)来拉取它显示的文本。
方便地,给定一个搜索字符串,QStandardItemModel::match 将返回一个 QModelIndexList,其中包含在列中匹配的每个 QModelIndex。当然,如果每一行都有几列,则需要对每一列执行此匹配,但我稍后会担心性能问题。
太棒了,这个问题解决了。我们有每个具有匹配字符串的 QModelIndex 的列表。现在,我想做的是在每一列中突出显示该字符串。例如:
搜索字符串:“col”
这是一个column |这是一个列umn |这是一个列umn |这是一个合作
突出显示的部分是我上面用粗体显示的部分。为了实现这一点,我通过阅读模型/视图文档知道我需要继承一个 QStyledItemDelegate 并重新实现它的绘制函数。所以我从那里开始。
下一个要解决的问题是,究竟如何在 DisplayRole 中选择一段特定的文本并仅突出显示它?您不能使用 Qt::BackgroundRole,它会设置整个索引的背景颜色。输入 QTextDocument。
我仍然需要做更多的挖掘工作,看看我如何能准确地实现这种行为,但是根据我在 Qt IRC 中被告知的内容,QTextEdit 有一个名为 setExtraSelections 的函数。看看它是如何实现的,它利用了 QAbstractTextDocumentLayout::Selection 和 QTextDocument 中可供我使用的各种光标函数。
但是,遗憾的是,我什至无法开始解决这个问题,因为第一步实际上是确保我可以使用重新实现的自定义委托绘制函数将 QTextDocument 渲染到 QTableView。这是我目前卡住的地方。我看过这篇文章,这里和它引用的那个:
Similar question that doesn't solve my issue
这并不是我想要的,但我认为它至少可以帮助我获得一些渲染效果。看起来在他的代码中,他正在绘制控件(这实际上是 QStyledItemDelegate 所做的),然后尝试在其上绘制他的 QTextDocument。也许那不是它正在做的事情,但它确实看起来像。
无论如何,当我尝试这样做时,看起来 QTextDocument 没有任何效果。如果我注释掉 drawControl 调用,则根本不会呈现任何文本。这是我的代码:
void CustomDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
if (index.column() == contentColumn)
{
painter->save();
QTextDocument contentDocument;
//opt.widget->style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
opt.text = "Things";
painter->setBrush(QBrush(Qt::darkCyan));
contentDocument.drawContents(painter, opt.rect);
painter->restore();
}
else
{
QStyledItemDelegate::paint(painter, option, index);
}
}
您可以看到我刚刚输入了文本“事物”以查看是否可以将其渲染。无济于事。
在总结我的问题之前,我想提一下,不,我不能使用 QTextEdit。有些特定的列我需要自动换行,而其他列我不想自动换行。 QTableView 完全按照我的预期显示数据。
所以我的问题是: 通过子类 QStyledItemDelegate 的绘制事件呈现 QTextDocument 是否是处理此问题的首选方式?如果没有,我应该怎么处理?
如果是这样,我该如何让它按预期工作?我的代码有什么问题?
奖金 2 合作伙伴问题 一旦可以渲染,我如何才能真正利用 QTextDocument API 仅突出显示特定部分,因为包含要突出显示的文本的模型索引列表是在完全不同的函数中发现的,并且在与绘制函数不同的时间发现执行?
更新 0 使用 QTextDocument API 进行多项选择看起来是不可能的壮举。我将要绘制内容的列需要自动换行和展开。
据我所知,我手动调用 drawContents 意味着手动处理调整大小、自动换行和许多其他事情,如果确实如此,我不想走这条路。
我想到了另一种方法,如果可行,我会更新。
更新 1 我以另一种方式完成了我想要的。不幸的是,我不能将 Qt 用于我想要的。 Qt 的模型/视图系统效率太低了,让它做我需要的事情会导致它非常慢且无法接受。我是如何完成突出显示的?
我将在答案中描述。如果没有人给我更好的答案,我会选择最好的。
【问题讨论】: