qt 富文本 打印

.QTextEdit的使用

rich text是用html标签表示的形式。text edit可以显示plain text(纯文本)html文件。

setHtml(), toHtml()返回HTML格式中的文本,用来控制内容到html的转换,还有清除内容。

插入内容:insertHtml(), insertPlainText(), append()

设置当前character的属性: setFontUnderline()(设置字体下划线), setFontFamily()(设置字体类型), setFontPointSize()(设置字体点大小)setCurrentFont()(设置现在的字体).

.QTextDocument组成

QTextDocument存放结构化的rich text文件,每个元素都有对应的格式对象。可以通过objectForFormat()来通过格式对象查找元素。QTextDocument能够忽略不能理解的标记。

可以通过QTextCursor来编程编辑QTextDocument对象,并对其进行填充。通过rootFrame()方法得到根节点再遍历其中的元素。如果只是浏览其中的文本文

档,就用begin(),end(),findBlock()方法。

文本的格式由documentLayout()决定.metaInformation()来的到文件的元信息。

toPlainText()toHtml()方法能够得到它text形式的内容和html形式的内容。

在 QTextDocument 类中包括一些通用的元素,例如 QTextBlock(段落)QTextFrame(框架)QTextTable(表格和 QTextList(列表描述。

图片使用一种特殊的文本片段描述。在更低的层次上,这些元素都有自己的描述属性,如文本风格和对齐方式。

文档的基本构建单位是QTextBlockQTextFrame。块本身就包含文本片段(QTextFragment),但是这不会直接影响到高层次的文档结构。

框架和表格用于组织其他结构,而文本块则包含真正的文本信息。每一个文档都包括一个根框架(root frame),以及至少一个文本块。

root frame决定显示的方式和布局。框架提供不同文档部分的逻辑分割,同时也提供了在渲染时如何显示的属性。一个表格就是一个特化的

框架,包含分布在不同行和列的多个单元。每个单元都能够包含更多的结构和文本。表格提供了灵活配置单元的管理和布局的特性。

文本块包含文本片段。每一个文本片段都有特定的文本和字符格式信息。文本属性在字符级别和块级别定义。在字符级别可以指定字体、颜

色和大小。在块级别可以指定更高一级的行为,例如文本流方向、对齐方式和背景色。

对文本块分组的是 QTextBlockGroup 的子类,对文本片段和其他元素分组的是 QTextFrame 的子类。

.开始使用QTextDocument

1.创建富文本

QTextDocument *newDocument = new QTextDocument;

也可以通过已有的文本组件获得:

QTextEdit *editor = new QTextEdit;

QTextDocument *editorDocument = editor->document();

新元素的创建和插入可以通过使用 QTextCursor 以编程的方式实现,或者通过 QTextEdit 以用户可视化编辑的方式实现。元素可以在创建时

指定一个特定的样式,或者是直接使用当前光标所在位置的样式。

QTextDocumentFragment用来保存QTextDocument的任意片段的,可以包含段落,表格,甚至一个完整的QTextDocument。当用户做出选择时,可以通过QTextCursor::selection()

获取用户选择的内容,它返回一个QTextDocumentFragment

2.访问根框架

QTextDocument *textDocument;

QTextFrame *root = textDocument->rootFrame();

根框架提供了访问整个文档结构的能力。根下的每个框架都包含一个文本块(可能为空)

.元素详解

1.文本块

文本块由 QTextBlock 类提供。除最后一页外的其他也,在最后部分放入一个分页符。通过创建一个新的QTextBlockFormat来实现,并把它的分页策略设置成Page_AlwaysAfter;

QTextCursor::mergeBlockFormat()方法用传递给它的任意非默认设置覆盖当前块格式的设置。QTextCursor::mergeCharFormat()方法,用来合并字符格式的各种设置。

QTextCursor::insertText()可使用任何已起作用的有效格式插入文本。QTextCursor::insertBlock()即可接受文本块格式由可接受字符文本格式。

文本块可以将具有不同字符样式的文本分组,用于表示文档段落。典型的文本块具有若干个不同样式的文本片段。当文本插入文档时,文本块被

创建。在对文档进行编辑时,会增加更多的文本块。在块中,文档通过分割、合并、删除片段,有效地表现不同样式的文本。

qt通常把一个文本块(即便为空)当做一个框架或者表格间的分隔符。

一个文本块中的片段可以通过 QTextBlock::iterator 遍历:

QTextBlock::iterator it;

for(it = currentBlock.begin(); !(it.atEnd()); ++it) {

QTextFragment currentFragment = it.fragment();

if(currentFragment.isValid())

processFragment(currentFragment);

}

}

块自己的样式由 QTextBlockFormat 描述,包括文本对齐方式,缩进和背景色。只要我们有一个文档中的文本块,就可以通过这个文本块对文档中所有文本块以编写顺序进行导航:

QTextBlock currentBlock = textDocument->begin();

while(currentBlock.isValid()) {

processBlock(currentBlock);

currentBlock = currentBlock.next();

}

当你需要导出文档中所有富文本内容时,这个方法就十分有用。因为它会忽略框架、表格以及其他文档结构。

2.框架

框架由 QTextFrame 类提供。0个或多个QTextFragment组成一个文本块,这些文本的属性(字体,下划线等)存储在一个单独的QTextCharFormat中。

文本框架用于组织文本块和子框架。这是一种比段落更大一级的文档结构。框架的格式决定它如何被显示和在页面中的位置。每一个文档都有一个根框架,包含了文档的所有结构。

除根框架之外,所有框架都有父框架。

既然文本块用于分割文档结构,那么,每一个框架都将至少包含一个文本块,零个或者多个子框架。我们可以通过 QTextFrame::iterator 来遍历所有子元素:

QTextFrame::iterator it;

for(it = frame->begin(); !(it.atEnd()); ++it) {

QTextFrame *childFrame = it.currentFrame();

QTextBlock childBlock = it.currentBlock();

if(childFrame)

processFrame(frameElement, childFrame);

elseif(childBlock.isValid())

processBlock(frameElement, childBlock);

}

3.表格

表格由 QTextTable 类提供。QTextTable类的属性(对其,单元格填充,单元格间距,列表数等)存储在单独的QTextTableFormat中。表格单元由QTextTableCell类表示,它可以包含文

本块或框架。单元格知道自己在表格中的位置(她们所在的行和列),单元格还拥有列和行的宽度属性和一个QTextCharFormat

表格是一个分布在行和列的单元的集合。每一个表格单元都是一个文档元素,拥有自己的字符样式,能够包含其他元素,例如框架和文本块。在表格构建,或者增加行或者列时,表格单

元被自动创建。表格单元也可以在两个表格之间移动。

QTextTable 是 QTextFrame 的子类,因此表格在文档中被作为框架处理,属性都存储在一个单独的QTextFrameFormat中。QTextTableCell::firstCursorPosition()在单元格中检索光标,

并使用此光标插入一个拥有我们创建的块格式的空段落,再使用QTextCursor::insertImage()方法把图片插入到这个段落中。如果我们需要处理文档中的每一个框架,我们需要对它们进行

区分,从而分别处理:

QTextFrame::iterator it;

for(it = frame->begin(); !(it.atEnd()); ++it) {

QTextFrame *childFrame = it.currentFrame();

QTextBlock childBlock = it.currentBlock();

if(childFrame) {

QTextTable *childTable = qobject_cast(childFrame);

if(childTable)

processTable(frameElement, childTable);

else

processFrame(frameElement, childFrame);

} else if (childBlock.isValid())

processBlock(frameElement, childBlock);

}

对于表格中已存在的单元,可以通过行和列进行遍历:

for(int row = 0; row < table->rows(); ++row) {

for(int column = 0; column < table->columns(); ++column) {

QTextTableCell tableCell = table->cellAt(row, column);

processTableCell(tableCell);

}

}

4.列表

列表由 QTextList 类提供。一个QTextList由一个或多个QTextBlock组成,这些QTextBlock的属性存储在一个单独的QTextListFormat--包括段落的对其,边距,缩进等。

列表是一系列按照一般方法格式化的文本块,同时有一个列表的修饰,例如一个点和列表项。列表可以嵌套。如果列表格式指定了非零缩进,列表就会有一定的缩进。如果文本块代

表一个列表,QTextBlock::testList()方法返回一个指向QTextList的指针;否则返回0.

我们可以通过列表索引指定每一个列表项:

for(int index = 0; index < list->count(); ++index) {

QTextBlock listItem = list->item(index);

processListItem(listItem);

}

当我们遍历文档的所有文本块时,有可能它是一个列表中的一项。我们应当使用下面的代码进行区分:

QTextFrame::iterator it;

for(it = frame->begin(); !(it.atEnd()); ++it) {

QTextBlock block = it.currentBlock();

if(block.isValid()) {

QTextList *list = block.textList();

if(list) {

intindex = list->itemNumber(block);

processListItem(list, index);

}

}

}

5.图像

在 QTextDocument 中,图像当做一个文本片段,这个文本通过 Qt 资源机制指向图片的外部链接。图像用QTextFragment中包含的占位符来表示。这个占位符有一个用来保存图像

尺寸和名称的QTextImageFormat(QTextCharFormat子类)。名称是应用程序资源中一幅图像的名称。

图像通过光标接口创建,通过改变图像文本片段的样式进行修改:

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);

}

}

表示图像的片段可以通过遍历包含图像的文本块的所有片段获得。

6.QTextCursor

QTextCursor是专门用来协助处理和获取QTextDocument内容的一组api. 它包含的信息既有QTextDocument内的光标位置(position()),以及所做的selection

anchor() 和 position()之间)。最后得调用QPlainTextEdit::setTextCursor()来修改光标,让我们所做的修改应用到文档。QTextCursor::select()方法可以用来选择当前行

(QTextCursor::LineUnderCurso),当前段落(QTextCursor::BlockUnderCursor),甚至整个文档(QTextCursor::Document).QPlainTextEdit::cursorRext()方法返回文本光标的矩

形框,我们需要设定矩形框的宽度,让他足够显示弹出列表的第一列,同时考虑一个垂直滚动条的宽度。

current character是指position之前的那个character. current block是指包含position()位置的block.QTextCursor::movePosition()方法把光标移动到已完成的单词后面。

方法:

setPosition(), movePosition() 可以用来创建selection。取得selection的内容:selectionStart(), selectionEnd(), hasSelection(), clearSelection(), andremoveSelectedText().

取得format信息:charFormat(), blockFormat().

设置format信息:setCharFormat(),mergeCharFormat(),setBlockFormat() andmergeBlockFormat(). merge会把本来的格式合并。当当前有selection时,char format会对应

到所选中的内容上;即使block没有全选,block format会应用于整个block.

插入文本:insertText() function, insertBlock(). insertList()insertTable()insertImage()insertFrame()

action可以分组(被undo/redo当作一个操作):beginEditBlock() and endEditBlock().

QTextCursor可以用来插入table,list,text,还用来创建selection和修改selectionTo select text between two points in the document, we need to position the cursor at 

the first point then move it using a special mode (QTextCursor::MoveMode) with a move operation (QTextCursor::MoveOperation). When we select the text, we leave

 the selection anchor at the old cursor position just as the user might do by holding down the Shift key when selecting text:

     cursor.movePosition(QTextCursor::StartOfWord);

     cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);

QTextDocument provides a cursor-based interface for searching, making it easy to find and modify text in the style of a text editor. The 

following code finds all the instances of a particular word in a document, and changes the color of each:

     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);

         }

     }

QTextCursor的一些用法

if (!currentTextCursor.hasSelection()) {

currentTextCursor.insertText("**" + tr("Boldface") + "**");

currentTextCursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 2);

currentTextCursor.movePosition(QTextCursor::WordLeft, QTextCursor::KeepAnchor, 1);

currentTextEdit->setTextCursor(currentTextCursor);

} else {

currentTextCursor.insertText("**" + currentTextCursor.selectedText() + "**");

}

1.在程序执行过程中去翻看前面的 信息,如果不把光标(虽然光标看不见)定位到最后一行,就会从翻看的位置打印信息。有没有把光标定位到最后的API

解决:

QTextCursor cursor = this->textCursor();

if(!cursor.atEnd())

{

cursor.movePosition(QTextCursor::End,QTextCursor::MoveAnchor,1);

this->setTextCursor(cursor); 

}

cursor.insertText(str);

QTextBlock:

组成QTextDocument的列表结构。

QTextBlock表示QTextDocument中的一个片断。它提供了其中的一个只读的block/paragraph. 它主要用来遍历text document来实现定制的layout或者重写一个新

document. 可以通过text()length()(包括了格式化的字符)得到文件内容的信息。

它的格式和QTextBlockFormat,QTehextCharFormat,QTextLayout都有关系。

如果要改变document的内容,请用QTextCursor接口。

qt 富文本 打印_第1张图片

.打印

本质上讲,将内容画在屏幕上和画在打印机上是一样的,但打印机上的坐标是实实在在的厘米,英寸,还有需要换页,这就需要你在画的时候计算好大小。

有几个有用的函数:

setOrientation()打印机定向

setPaperSize()设置纸张大小

setResolution()设置DPI

newPage()新的一页

setNumCopies()打印多少份

需要注意的是:

1、当调用painter.begin后默认就会创建一个空白页,所以一开始不需要newpage,直接画就是了;

2、在一页画完以后直接调用print.newpage创建新页面

3、直到所有页面画完后才可以调用painter.end().

4printer对象的pagerect返回的是去掉页边距后的矩形;paperrect返回的是纸张大小(单位可以设置)

5.QPrinter::paperRect()作为自己打印区域来给页码编数。

首先看一个简单的例子,打印一个QImage到一页纸上。

void PrintWindow::printImage(const QImage&image)

{

QPainter painter(&printer);

QRect rect=painter.viewport();

QSize size=image.size();

size.scale(rect.size(),Qt::KeepAspectRatio);

painter.setViewport(rect.x(),rect.y(),

size.width(),size.height());

painter.setWindow(image.rect());

painter.drawImage(0,0,image);

}

创建QPainter,绘图设备为QPrinter。设置窗口为所显示图形的矩形,视口也同样比例,然后在(00)绘制图像。

通常,QPainter的窗口自动进行了初始化,打印机和屏幕有着一致的分辨率,使控件的打印代码能够重用

调用printHtml()打印html

void PrintWindow::printHtml(const QString&html)

{

QPainter painter(&printer);

QTextDocument textDocument;

textDocument.setHtml(html);

textDocument.print(&printer);

}

把文本转换为HTML文档用QTextDocument打印是最方便的一个方法。

调用printPage()按照顺序和打印份数打印每一页,设置了打印范围,或者要求逆序打印。我们需要在程序中考虑这些需求:

首先确定打印范围。QPrinter::fromPage()toPage()返回用户选择的页面范围。如果没有选择,返回为0。我们进行了减1操作是因为我们的页面索引是从0开始的。

如果用户没有选定范围,则打印全部,firstPagelastPage包含量所有的页面。

然后我们打印每一页。最外层循环为用户设定的打印的份数。对于那些支持多份打印的打印机,QPrinter::numCopies()总是返回1。如果打印机驱动程序不支持多份

打印,numCopies()返回到是用户指定的打印份数,有应用程序实现多份打印。

内层循环遍历打印的页数。如果页数不是第一页,调用newPage()清楚原来的页面开始填充新页面。调用printPage()打印每一页。

void PrintWindow::printPage(QPainter*painter,

const QStringList&entries,int pageNumber)

{

painter->save();

painter->translate(0,LargeGap);

foreach(QString entry,entries){

QStringList fields=entry.split(":");

QString title=fields[0];

QString body=fields[1];

printBox(painter,title,titleFont,Qt::lightGray);

printBox(painter,body,bodyFont,Qt::white);

painter->translate(0,MediumGap);

}

painter->restore();

painter->setFont(footerFont);

painter->drawText(painter->window(),

Qt::AlignHCenter|Qt::AlignBottom,

QString::number(pageNumber));

}

函数printPage()打印页面中的每一个条目。首先用printBox()打印标题,然后用printBox()打印描述。在每一页的底端打印页码。

void PrintWindow::printBox(QPainter*painter,const QString&str,

const QFont&font,const QBrush&brush)

{

painter->setFont(font);

int boxWidth=painter->window().width();

int textWidth=boxWidth-2*SmallGap;

int maxHeight=painter->window().height();

QRect textRect=painter->boundingRect(SmallGap,SmallGap,

textWidth,maxHeight,

Qt::TextWordWrap,str);

int boxHeight=textRect.height()+2*SmallGap;

painter->setPen(QPen(Qt::black,2,Qt::SolidLine));

painter->setBrush(brush);

painter->drawRect(0,0,boxWidth,boxHeight);

painter->drawText(textRect,Qt::TextWordWrap,str);

painter->translate(0,boxHeight);

}

printBox()首先绘制一个矩形框,然后在矩形框中绘制文本。

 

你可能感兴趣的:(qt)