描述
我创建了一个 TextArea
QML 中的组件,类似于 this例如,我基于指向 QQuickTextDocument
的指针创建了一个 DocumentHandler 类。 ,这是通过 textDocument 获取的属性(property)。我需要这个以便能够格式化文本,即使其粗体、下划线、斜体、删除线等。
我需要什么
我需要获取一个文本,其中格式化部分将显示为 HTML 标记。
例如粗体文本最终我想采用<b>Bold text</b>
形式。或者例如粗体和斜体文本我想采用<b><i>Bold and italic text</i></b>
形式(标签放置的顺序并不重要)。
我尝试了什么
我尝试使用 toHtml()函数,但这个函数不适合我,因为:
- 它会生成很多我不需要的不必要信息。例如,对于粗体文本,它返回以下结果:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'Roboto'; font-size:14px; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Bold text</span></p></body></html>
- 我需要表示文本的常用标签(
<b>
、<i>
等),该函数以style
的形式形成<span>
的属性标签。因此它用这一行更改了粗体:<span style=" font-weight:600;">
.
最佳答案
描述
如果我理解正确的话,目前没有办法在没有 QTextDocument
生成的元信息的情况下获取带有 HTML 标签的格式化文本。使用toHtml()
功能。因此,我决定使用 QTextCursor
手动完成这项工作。类。
代码
我有一个提供有关标签信息的结构:
struct Tag
{
Tag() = default;
Tag(const QString& openTag,
const QString& closeTag,
const std::function<bool(const QTextCursor& cursor)>& canBeOpened);
QString getOpenTag() const
{
return m_openTag;
}
QString getCloseTag() const
{
return m_closeTag;
}
bool canBeOpened(const QTextCursor& cursor) const
{
return m_canBeOpened(cursor);
}
private:
QString m_openTag;
QString m_closeTag;
std::function<bool(const QTextCursor&)> m_canBeOpened;
};
我有一个std::vector
我初始化如下的此类结构:
m_tags{ { "<b>", "</b>", [](const QTextCursor& cursor) { return cursor.charFormat().fontWeight() == QFont::Bold; } },
{ "<i>", "</i>", [](const QTextCursor& cursor) { return cursor.charFormat().fontItalic(); } },
{ "<u>", "</u>", [](const QTextCursor& cursor) { return cursor.charFormat().fontUnderline(); } },
{ "<s>", "</s>", [](const QTextCursor& cursor) { return cursor.charFormat().fontStrikeOut(); } } }
最重要的是getFormattedText()
使用 Tag
这个向量的函数对象返回格式化文本。主要思想是手动在纯文本中放置标签,即开始标签放置在格式开始的地方,结束标签放置在格式结束的地方。有关文本中何处使用什么格式的信息可以从 QTextCursor
获取。类,我们的对象 can create基于QTextDocument
类(class)。结果,我们有以下功能:
QString getFormattedText()
{
auto cursor{ textCursor() };
if (!cursor.isNull())
{
int offset{};
auto result{ cursor.document()->toPlainText() };
auto currentTextFormat{ getTextFormat() };
for (int i{}; i < cursor.document()->characterCount(); ++i)
{
cursor.setPosition(i);
const auto localTextFormat{ getTextFormat(cursor) };
if (currentTextFormat != localTextFormat)
{
const auto closedFormat{ getClosedFormat(currentTextFormat) };
const auto openedFormat{ getOpenedFormat(localTextFormat) };
result.insert(i - (i > 0 ? 1 : 0) + offset, closedFormat + openedFormat);
offset += closedFormat.size() + openedFormat.size();
currentTextFormat = localTextFormat;
}
}
result += getClosedFormat(currentTextFormat);
return result.replace("\n", "<br>");
}
return {};
}
与 currentTextFormat
相关的逻辑和localTextFormat
为了“及时”关闭一种格式组合并打开一种新格式,变量是必要的。这种格式的组合被命名为:
using TextFormat = std::vector<std::pair<FontFormat, bool>>;
哪里FontFormat
是:
enum class FontFormat
{
Bold,
Italic,
Underline,
Strikethrough
};
获取TextFormat
的函数:
TextFormat getTextFormat()
{
TextFormat textFormat;
for (const auto& format : m_formats)
{
textFormat.push_back({ format.first, false });
}
return textFormat;
}
TextFormat getTextFormat(const QTextCursor& cursor)
{
TextFormat textFormat;
for (const auto& format : m_formats)
{
textFormat.push_back({ format.first, format.second.canBeOpened(cursor) });
}
return textFormat;
}
获取 TextFormat
文本解释的函数:
QString getOpenedFormat(const TextFormat& textFormat)
{
const auto append = [](QString& result, const Tag& tag) {
result.push_back(tag.getOpenTag());
};
return getFormat(textFormat, append);
}
QString getClosedFormat(const TextFormat& textFormat)
{
const auto append = [](QString& result, const Tag& tag) {
result.prepend(tag.getCloseTag());
};
return getFormat(textFormat, append);
}
QString getFormat(const TextFormat& textFormat, const std::function<void(QString&, const Tag&)>& append)
{
QString result;
for (const auto& format : textFormat)
{
if (format.second)
{
const auto fndFontFormat{ m_formats.find(format.first) };
if (fndFontFormat != m_formats.end())
{
append(result, fndFontFormat->second);
}
}
}
return result;
}
例如有这样的文字:abc。本文的每个字母都有不同的格式组合,当从一个字母迭代到另一个字母时,有必要考虑到这一点,关闭旧的组合并打开一个新的组合。
因此 abc 将转换为:<b>a</b><b><s>b</b></s><s>c</s>
.
关于qt - 如何从组件 QTextDocument 获取没有元信息的 HTML 文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67920546/