目录(?)[+]
目录(?)[+]
Scribe框架提供一系列读和控制富文本文档的类。Qt4提供像QTextDocument类,他能够为开发提供创建和修改结构的富文本文档。
文档内的信息通过两个补充的接口存取:
1. 基于光标的接口用来编辑。2. 可读的分层接口它提供文档结构的高层次预览。使用前者的优点是他可以使用操纵符编辑,提供了一个很好的用户交互接口,不会损失潜在的文档结构。而后者的接口在查询和文档展示时最有用。
帮助文档分为了六个章节来介绍Rich Text Processing,可以仔细查阅:
Rich Text Document Structure
The QTextCursor Interface
Document Layouts
Common Rich Text Editing Tasks
Advanced Rich Text Processing
Supported HTML Subset
QTextDocument类是文本文档的代表,它包含了构建富文本文档所需的信息。文档的结构是由分层的文本块(text blocks),frames,tables和一些其他的内容对象组成。新元素的创建和插入可以使用QTextCursor或者editor widget(例如QTextEdit)。如下图表示了他们的分层结构:
使用QTextEdit使展示编辑富文本非常容易,文档可以为任何编辑部件无关地创建,例如:
QTextDocument *newDocument = new QTextDocument;
也可以为已存在的编辑部件创建:
QTextEdit *editor = new QTextEdit;
QTextDocument *editorDocument = editor->document();
一个空文档包含一个root frame,这个root frame自己是包含一个空text block的。Frame不仅有分隔文档的功能,也有提供如何显示的功能。下面是获得root frame的方法:
QTextDocument *textDocument;
QTextFrame *root = textDocument->rootFrame();
Table是frame的专门类型,由一些单位(cells)组成,它们被安排成行和列,每一个都包含结构和文本。Table提供管理和呈现的特征,这样可以灵活的创建单位。Text blocks包含特殊化的文本和字符格式信息,例如字符的颜色,对齐,背景等等。以上的元素对应的类是QTextFrame, QTextTable, QTextBlock, (还有一个对应列表的类QTextList)。图片元素由特殊的text block代表。一组元素可以一起子类化为QTextBlockGroup,QTextBlockGroup是QTextFrame子类。
Text blocks可以通过QTextBlock::iterator遍历块的内部结构:
QTextBlock::iterator it;
for (it = currentBlock.begin(); !(it.atEnd()); ++it) {
QTextFragment currentFragment = it.fragment();
if (currentFragment.isValid())
processFragment(currentFragment);
}
QTextBlock提供了比较操纵符:== != <用来判断两个块是否相同,出现的先后。
Text frames可以由一组块和子frames组成。所有的frame除了root frame,都有父frame。使用QTextFrame::iterator遍历frame的子元素:
QDomElement frameElement = ...
QTextFrame::iterator it;
for (it = frame->begin(); !(it.atEnd()); ++it) {
QTextFrame *childFrame = it.currentFrame();
QTextBlock childBlock = it.currentBlock();
if (childFrame)
processFrame(frameElement, childFrame);
else if (childBlock.isValid())
processBlock(frameElement, childBlock);
}
QTextTable是QTextFrame的子类,所以tables可以像对待QTextFrame一样对待。它每一个单位(cell)的检查可以通过行列号:
for (int row = 0; row < table->rows(); ++row) {
for (int column = 0; column < table->columns(); ++column) {
QTextTableCell tableCell = table->cellAt(row, column);
processTableCell(tableCell);
}
}
QTextList是QTextBlockGroup的子类,它可以使用索引获得QTextList对象的项。
for (int index = 0; index < list->count(); ++index) {
QTextBlock listItem = list->item(index);
processListItem(listItem);
}
Images在QTextDocument中由text fragment代表,由光标(cursor)接口创建,可以被字符格式修改:
if (fragment.isValid()) {
QTextImageFormat newImageFormat = fragment.charFormat().toImageFormat();
if (newImageFormat.isValid()) {
newImageFormat.setName(":/images/newimage.png");
QTextCursor helper = cursor;
helper.setPosition(fragment.position());
helper.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor);
helper.setCharFormat(newImageFormat);
}
}
文档可以通过QTextCursor提供的接口编辑,
使用cursor主要是用来插入或修改块中的文本,我们可以在编辑器中使用:
QTextEdit *editor = new QTextEdit();
QTextCursor cursor(editor->textCursor());
也可以直接从一个文档中获取。
QTextDocument *document = new QTextDocument(editor);
QTextCursor cursor(document);
一系列的编辑操作可以打包到一起去,这样可以使用beginEditBlock(),endEditBlock()实现,下面代码示例:
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::StartOfWord);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
cursor.endEditBlock();
QTextCursor提供一些插入文档元素的操作:
insertBlock()
insertFrament()
insertImage()
insertText()
以上都不会返回插入元素,下面的操作会返回插入的元素:
insertFrame()
insertList()
insertTable()
一下是一些示例:
// insert Text
cursor.insertText(tr("Character formats"),
headingFormat);
cursor.insertBlock();
cursor.insertText(tr("Text can be displayed in a variety of " "different character formats. "), plainFormat); // 以某格式插入文本
cursor.insertText(tr("We can emphasize text by "));
cursor.insertText(tr("making it italic"), emphasisFormat);
// insert block
QTextBlockFormat backgroundFormat = blockFormat;
backgroundFormat.setBackground(QColor("lightGray"));
cursor.setBlockFormat(backgroundFormat);
// insert frame
QTextFrame *mainFrame = cursor.currentFrame();
cursor.insertText(...);
// 为子frame建立一个frame格式
QTextFrameFormat frameFormat;
frameFormat.setMargin(32);
frameFormat.setPadding(8);
frameFormat.setBorder(4);
QTextFrameFormat的格式示意图:
cursor.insertFrame(frameFormat);
cursor.insertText(...);
插入table:
QTextCursor cursor(editor->textCursor());
QTextTable *table = cursor.insertTable(rows, columns, tableFormat);
它也可以定义格式:
QTextTableFormat tableFormat;
tableFormat.setBackground(QColor("#e0e0e0"));
QVector<QTextLength> constraints;
constraints << QTextLength(QTextLength::PercentageLength, 16);
constraints << QTextLength(QTextLength::PercentageLength, 28);
constraints << QTextLength(QTextLength::PercentageLength, 28);
constraints << QTextLength(QTextLength::PercentageLength, 28);
tableFormat.setColumnWidthConstraints(constraints);
QTextTable *table = cursor.insertTable(rows, columns, tableFormat);
插入list:
QTextListFormat listFormat;
if (list) {
listFormat = list->format();
listFormat.setIndent(listFormat.indent() + 1);
}
listFormat.setStyle(QTextListFormat::ListDisc);
cursor.insertList(listFormat);
插入images:
QTextImageFormat imageFormat;
imageFormat.setName(":/images/advert.png");
cursor.insertImage(imageFormat);:
每个文档的布局都是子类化的QAbstractTextDocumentLayout类。QTextLayout可以帮助开发者呈现渲染文本,它可以用在plain和rich text。QTextLine是QTextLayout内的一排文本,可以QTextLayout::createLine()创建。
下面是个例子:
QTextLayout textLayout(text, font);
qreal margin = 10;
qreal radius = qMin(width()/2.0, height()/2.0) - margin;
QFontMetrics fm(font);
qreal lineHeight = fm.height();
qreal y = 0;
textLayout.beginLayout();
while (1) {
// create a new line
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;
qreal x1 = qMax(0.0, pow(pow(radius,2)-pow(radius-y,2), 0.5));
qreal x2 = qMax(0.0, pow(pow(radius,2)-pow(radius-(y+lineHeight),2), 0.5));
qreal x = qMax(x1, x2) + margin;
qreal lineWidth = (width() - margin) - x;
line.setLineWidth(lineWidth);
line.setPosition(QPointF(x, margin+y));
y += line.height();
}
textLayout.endLayout();
QPainter painter;
painter.begin(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.fillRect(rect(), Qt::white);
painter.setBrush(QBrush(Qt::black));
painter.setPen(QPen(Qt::black));
textLayout.draw(&painter, QPoint(0,0));
painter.setBrush(QBrush(QColor("#a6ce39")));
painter.setPen(QPen(Qt::black));
painter.drawEllipse(QRectF(-radius, margin, 2*radius, 2*radius));
painter.end();
我们通常用QTextBrowser和QTextEdit完成富文本编辑任务,通过QTextDocument创建文档,QTextCursor编辑,用文档结构展示。
例如利用文本编辑器部件展示HTML:
QTextEdit *editor = new QTextEdit(parent);
editor->setHtml(aStringContainingHTMLtext);
editor->show();
默认情况下,文本编辑器包含一个带有root frame的文档,可以editor->document()获得,可使用editor->textCursor()获得编辑器的光标QTextCursor。
选择文本,通过移动光标,例如:QTextCursor::MoveMode(MoveAnchor, KeepAnchor)
cursor.movePosition(QTextCursor::StartOfWord);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
查找文本,下面是查找一个单词,并改变它的颜色以显示:
QTextCursor newCursor(document);
while (!newCursor.isNull() && !newCursor.atEnd()) {
newCursor = document->find(searchString, newCursor);
if (!newCursor.isNull()) {
newCursor.movePosition(QTextCursor::WordRight,
QTextCursor::KeepAnchor);
newCursor.mergeCharFormat(colorFormat);
}
}
打印文本,QTextEdit可以自动在一页大小的地方断开,以适应打印。QTextDocument提供print()函数允许打印。例如所示代码:
QTextDocument *document = editor->document();
QPrinter printer;
QPrintDialog *dlg = new QPrintDialog(&printer, this);
if (dlg->exec() != QDialog::Accepted)
return;
document->print(&printer);
处理大文件
Qt 不限制文本处理的文件大小,对于大多数情况而言,这将不会出现问题。文件大小依赖于你硬件和你的Qt程序实现。
如果你面对了这个问题,我们推荐你
1. 你应该考虑断开大段成为更小的段落,你也可以定期插入换行符,这样就看起来像QTextEdit的一个大段。
2. 你可以在QTextDocument中用maximumBlockCount()减少块的数量,文档只和QTextEdit涉及到的块数量大小相当。
3. 当增加文本到一个文本编辑时,这是一个增加文本到编辑块(看下例)的优势。结果是文本编辑不是立刻需要全部文档结构的。
下面的例子我们假设文本编辑是可见的。
textEdit.show();
textCursor.beginEditBlock();
for (int i = 0; i < 1000; ++i) {
textCursor.insertBlock();
textCursor.insertText(paragraphText.at(i));
}
textCursor.endEditBlock();
Widgets使用QTextDocument能够展示特殊的富文本,例如QLabel, QTextEdit。
在Text Widget使用HTML标记
Widget会在展示时自动删除HTML标记,并根据含义展示富文本。例如,设置一个文本标签:"<b>Hello</b> <i>Qt!</i>",它会展示出这样:Hello Qt!
所支持的标记有:
Tag |
Description |
Comment |
a |
Anchor or link |
Supports the href and name attributes. Note that the :visited selector is one of those that is not supported by the rich text engine. See below for a list of others. |
address |
Address |
|
b |
Bold |
|
big |
Larger font |
|
blockquote |
Indented paragraph |
|
body |
Document body |
Supports the bgcolor attribute, which can be a Qt color name or a #RRGGBB color specification. |
br |
Line break |
|
center |
Centered paragraph |
|
cite |
Inline citation |
Same as i. |
code |
Code |
Same as tt. |
dd |
Definition data |
|
dfn |
Definition |
Same as i. |
div |
Document division |
Supports the standard block attributes. |
dl |
Definition list |
Supports the standard block attributes. |
dt |
Definition term |
Supports the standard block attributes. |
em |
Emphasized |
Same as i. |
font |
Font size, family, and/or color |
Supports the following attributes: size, face, and color (Qt color names or #RRGGBB). |
h1 |
Level 1 heading |
Supports the standard block attributes. |
h2 |
Level 2 heading |
Supports the standard block attributes. |
h3 |
Level 3 heading |
Supports the standard block attributes. |
h4 |
Level 4 heading |
Supports the standard block attributes. |
h5 |
Level 5 heading |
Supports the standard block attributes. |
h6 |
Level 6 heading |
Supports the standard block attributes. |
head |
Document header |
|
hr |
Horizontal line |
Supports the width attribute, which can be specified as an absolute or relative (%) value. |
html |
HTML document |
|
i |
Italic |
|
img |
Image |
Supports the src, source (for Qt 3 compatibility), width, and height attributes. |
kbd |
User-entered text |
|
meta |
Meta-information |
If a text encoding is specified using the meta tag, it is picked up by Qt::codecForHtml(). Likewise, if an encoding is specified toQTextDocument::toHtml(), the encoding is stored using a meta tag, for example: <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" /> |
li |
List item |
|
nobr |
Non-breakable text |
|
ol |
Ordered list |
Supports the standard list attributes. |
p |
Paragraph |
Left-aligned by default. Supports the standard block attributes. |
pre |
Preformated text |
|
qt |
Qt rich-text document |
Synonym for html. Provided for compatibility with earlier versions of Qt. |
s |
Strikethrough |
|
samp |
Sample code |
Same as tt. |
small |
Small font |
|
span |
Grouped elements |
|
strong |
Strong |
Same as b. |
style |
Style sheet |
Allows styling information to be included with the rich text. A limited subset of CSS syntax can be used to change the appearance of the text. |
sub |
Subscript |
|
sup |
Superscript |
|
table |
Table |
Supports the following attributes: border, bgcolor (Qt color names or #RRGGBB), cellspacing, cellpadding, width(absolute or relative), and height. |
tbody |
Table body |
Does nothing. |
td |
Table data cell |
Supports the standard table cell attributes. |
tfoot |
Table footer |
Does nothing. |
th |
Table header cell |
Supports the standard table cell attributes. |
thead |
Table header |
If the thead tag is specified, it is used when printing tables that span multiple pages. |
title |
Document title |
The value specified using the title tag is available through QTextDocument::metaInformation(). |
tr |
Table row |
Supports the bgcolor attribute, which can be a Qt color name or a #RRGGBB color specification. |
tt |
Typewrite font |
|
u |
Underlined |
|
ul |
Unordered list |
Supports the standard list attributes. |
var |
Variable |
Same as i. |
块block属性。这下面的属性被div, dl, dt, h1, h2, h3, h4, h5, h6, p支持:
align(left, right, center, justify)
dir(ltr, rtl)
列表list属性。下面的属性被ol, ul支持:
type (1, a, A, square, disc, circle)
表单位Table Cell属性。下面的被td, th标记支持:
width (absolute, relative, or no-value)
bgcolor (Qt color names or #RRGGBB )
colspan
rowspan
align (left, right, center, justify)
valign (top, middle, bottom)
CSS属性
Version:Property |
Values |
Description |
background-color |
<color> |
Background color for elements |
background-image |
<uri> |
Background image for elements |
color |
<color> |
Text foreground color |
font-family |
<family name> |
Font family name |
font-size |
[ small | medium | large | x-large | xx-large ] | <size>pt | <size>px |
Font size relative to the document font, or specified in points or pixels |
font-style |
[ normal | italic | oblique ] |
|
font-weight |
[ normal | bold | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 ] |
Specifies the font weight used for text, where normal and bold are mapped to the corresponding QFont weights. Numeric values are 8 times the equivalent QFont weight values. |
text-decoration |
none | [ underline || overline || line-through ] |
Additional text effects |
font |
[ [ <'font-style'> || <'font-weight'> ]? <'font-size'> <'font-family'> ] |
Font shorthand property |
text-indent |
<length>px |
First line text indentation in pixels |
white-space |
normal | pre | nowrap | pre-wrap |
Declares how whitespace in HTML is handled. |
margin-top |
<length>px |
Top paragraph margin in pixels |
margin-bottom |
<length>px |
Bottom paragraph margin in pixels |
margin-left |
<length>px |
Left paragraph margin in pixels |
margin-right |
<length>px |
Right paragraph margin in pixels |
padding-top |
<length>px |
Top table cell padding in pixels |
padding-bottom |
<length>px |
Bottom table cell padding in pixels |
padding-left |
<length>px |
Left table cell padding in pixels |
padding-right |
<length>px |
Right table cell padding in pixels |
padding |
<length>px |
Shorthand for setting all the padding properties at once. |
vertical-align |
baseline | sub | super | middle | top | bottom |
Vertical text alignment. For vertical alignment in text table cells only middle, top, and bottom apply. |
border-color |
<color> |
Border color for text tables. |
border-style |
none | dotted | dashed | dot-dash | dot-dot-dash | solid | double | groove | ridge | inset | outset |
Border style for text tables. |
background |
[ <'background-color'> || <'background-image'> ] |
Background shorthand property |
page-break-before |
[ auto | always ] |
Make it possible to enforce a page break before the paragraph/table |
page-break-after |
[ auto | always ] |
Make it possible to enforce a page break after the paragraph/table |
float |
[ left | right | none ] |
Specifies where an image or a text will be placed in another element. Note that the floatproperty is only supported for tables and images. |
text-transform |
[ uppercase | lowercase ] |
Select the transformation that will be performed on the text prior to displaying it. |
font-variant |
small-caps |
Perform the smallcaps transformation on the text prior to displaying it. |
word-spacing |
<width>px |
Specifies an alternate spacing between each word. |
支持CSS选择器,所有CSS2.1选择器都支持,除了pseudo-class选择器,例如:first-child, :visited 和 :hover
帮助文档中有四个Rich Text的例子:Calendar, Order Form, Syntax High Lighter, Text Object。本博客展示前两个。
这个例子很简单,MainWindow类里添加一个QTextBrowser私有对象,并将此对象默认关联的QTextCursor对象进行编辑。添加Table和Frame。
本例中使用到了QDate类,它是Qt专门用于处理日期的类,currentDate()获取系统的日期;setDate(),fromString()可以设置日期;year(),month(),day()返回日期的年,月,日;年月日的这信息可以有各种格式:
Expression |
Output |
d |
the day as number without a leading zero (1 to 31) |
dd |
the day as number with a leading zero (01 to 31) |
ddd |
the abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses QDate::shortDayName(). |
dddd |
the long localized day name (e.g. 'Monday' to 'Sunday'). Uses QDate::longDayName(). |
M |
the month as number without a leading zero (1 to 12) |
MM |
the month as number with a leading zero (01 to 12) |
MMM |
the abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses QDate::shortMonthName(). |
MMMM |
the long localized month name (e.g. 'January' to 'December'). Uses QDate::longMonthName(). |
yy |
the year as two digit number (00 to 99) |
yyyy |
the year as four digit number. If the year is negative, a minus sign is prepended in addition. |
(注意,Qt会默认使用系统的语言,例如中文的shortDayName()是周一,周二等,longDayName()是星期一,星期二等。)
增加日期的方法:addMonths(); addYears(); addDays();daysTo()可以比较两个日期相差天数。对于闰年:isLeapYear()返回是否闰年。
下面展示的是本例子的核心代码(关于Rich Text的):
本例是一个订货小模拟软件,主程序打开后生成一个默认的订单。菜单中选择File->New可以订购新订单:将弹出如图中的Details对话框。填写信息后点击OK,程序将为之创建一个订单标签展示于当前TabWidget中。这里只展示出在住程序中是如何编辑rich text的代码。