参考文章
hitzsf 博主
长沙红胖子qt 博主
如何查找电脑上字体名称
win+r的快捷键打开运行窗口。2、然后在输入框中输入control点击确定。3、在所有控制面板项 右边搜索框 输入“字体”--回车--查看安装的字体。
0-概述
QTextEdit 是一个部件,可以用来展示或编辑纯文本和富文本。
如果用来书写富文本的话,支持html的标签。当然,几个字的富文本,最好使用QLabel 。
纯文本,一行就相当于一个段落。
QTextBrowser是QTextEdit 的子类,功能增加了一个可以导航(添加超链接)。
对于这两种文本编辑器,代码方式有两种,一种是 (??这里我还没弄明白) ,另一种是基于游标来编辑,也就是说必须先获得QTextCursor。
0.1 游标的构造函数有3种:
从文本框QTextBlock中获得 QTextCursor(const QTextBlock &block)
从框架QTextFrame种获得 QTextCursor(QTextFrame *frame)
从文档QTextDocument获得 QTextCursor(QTextDocument *document)
拷贝构造函数和=号赋值重载函数。QTextCursor(const QTextCursor &cursor)
0.2 游标可以插入哪些文档元素
insertBlock 文本块
insertFragment 文本片段
insertFrame 文本框架
insertHtml(const QString &html) 网页
insertList 列表
insertTable(int rows, int columns) 表格,(父类是frame)
insertText(const QString &text) 文本
insertImage 图
0.3 光标位置操作函数
QTextCursor QTextFrame::firstCursorPosition() const
Returns the first cursor position inside the frame.注意,是在框架内的最前面的光标位置。
int QTextFrame::firstPosition() const
Returns the first document position inside the frame.意思跟上面那个方法一样,但是返回整数,意思是文档里的位置,(还是在框架内)。
1.QTextBlock Class -文本块
创建时选择widget 。在widget.h里面添加
#include<QTextEdit>
#include <QTextCursor>
#include <QTextBlockFormat>
widget.cpp 中代码如下:
1.1 QTextFormat
描述段落 格式。包括:
setBackground 段落背景 (参数可以是个QColor )
段落缩进 indent
段落margin --上下左右
首行缩进textIndent
1.2 QTextCharFormat
描述字符格式。
格式包括: setFont 字体( 字号,字体,加粗,)
setOverline 上滑线、下划线、
wordSpacing 单词间距、字母间距、
setVerticalAlignment 字符的垂直对齐(默认所有的字母都有一条看不见的基线,平时字母都是在基线中间)
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//the whole size
resize(900,700);
//CSDN
QTextEdit *editor = new QTextEdit(this);
//my change it bigger
editor->resize(850,650);
QTextCursor cursor(editor->textCursor());
cursor.beginEditBlock();
// cursor.insertText(tr("Character formats"));发现不写tr也行
cursor.insertText("Character formats");
//insertBlock重载版本1 作用:重新起一段
cursor.insertBlock();
cursor.insertText("Text can be displayed in a variety of different character
formats. ");
cursor.insertText("We can emphasize text by ");
cursor.insertText("making it italic");
// QTextBlockFormat Class 先设置block格式再插入文本块
QTextBlockFormat bf1;
//设置段落的背景
bf1.setBackground(QColor(190,150,200));
//设置行高,第一个参数是一个数字,整数小数都行。第二个参数有0 ,1 2 等多种value ,找
lineHeightTypes可以查询。
bf1.setLineHeight(120,1);
//SHEZHI 下边距
bf1.setBottomMargin(50);
cursor.setBlockFormat(bf1);
cursor.insertBlock();
cursor.insertText("setBlockFormat bf1 bf1 has a purple background color "
"先设置段落格式,然后插入文本块,然后插入text hah a this is written by me ");
//自学insertBlock 重载版本2
//void QTextCursor::insertBlock(const QTextBlockFormat &format)
QTextBlockFormat bf2;
//设置段落的背景
bf2.setBackground(QColor(210,108,120));
//设置行高,第一个参数是一个数字,整数小数都行。第二个参数有0 ,1 2 等多种value ,找
lineHeightTypes可以查询。
//只有一行的时候,第二个参数是2必须,不然设置多大都显示不出来
bf2.setLineHeight(200,1);
//SHEZHI 下边距
bf2.setBottomMargin(20);
//在段落中,首行缩进 参数是一个整数或者浮点数字 可以先测量出字符宽度然后写这个数
值*2
QFontMetrics fm(this->font());
bf2.setTextIndent(fm.averageCharWidth()*2);
//设置缩进,这个段落相对于部件的缩进, 参数必须是整数,文档范围的标准缩进
bf2.setIndent(1);
cursor.insertBlock(bf2);
cursor.insertText("QFontMetrics functions calculate the size of characters and strings for a given font. There are three ways you can create a QFontMetrics object:"
" QFont font('times', 24);QFontMetrics fm(font) QWidget::fontMetrics() returns the font metrics for a widget's font. This is equivalent to QFontMetrics(widget->font())");
//自学insertBlock 重载版本3
//void QTextCursor::insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat)
//self study :QTextCharFormat
QTextCharFormat cf1;
QFont qf1;
qf1.setOverline(true); //上划线
qf1.setFamily("Agency FB"); //字体
qf1.setPointSize(26);
//设置字体
cf1.setFont(qf1);
//设置单词之间的间距, 10比默认的大
cf1.setFontWordSpacing(10);
//字符的垂直对齐,是相对于 看不见的默认基线而言的,
//因为我弄了上划线,因为我想看到那个线所以设置了往下边对齐
cf1.setVerticalAlignment(QTextCharFormat::AlignSubScript);
//这个东西可能会影响字号
cursor.insertBlock(bf1, cf1);
cursor.insertText("cursor.insertBlock(bf1, cf1);//自学insertBlock 重载版本3//void QTextCursor::insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat)");
cursor.endEditBlock();
}
Widget::~Widget()
{
delete ui;
}
效果:
1.2.1 QTextImageFormat Class
QTextImageFormat Class是QTextCharFormat的子类,为QTextDocument 类中的图片提供格式。
2. QTextFragment Class
根据官方帮助文档,每个片段都有一个自己独特的QTextCharFormat。
即:格式不同的字体会被从段落中分割为fragment.
2.1 QTextFragment和block的关系:
QTextBlock的迭代器就是在各个fragment之间遍历。找到的每一个片段先判断是否有效,然后判断某种属性 。但是一旦插入新块 cursor.insertBlock ,再insertText 那么当前块的迭代器就找不到下一个片段了,例如,我将博主的代码里加入了 cursor.insertBlock 然后迭代器不管放在哪个块里 都找不到别的块里的fragment 了。但是测试结果 和cursor.endEditBlock();
头文件widget.h里添加
#include<QTextEdit>
#include <QTextCursor>
#include <QTextBlockFormat>
#include <QTextFragment>
#include <QDebug>
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->setupUi(this);
//the whole size
resize(900,700);
//CSDN
QTextEdit *editor = new QTextEdit(this);
//my change it bigger 设置自己的偏好字体
editor->resize(850,650);
QTextDocument *doc = editor->document(); //获取文本文档
QFont myfont("Bahnschrift",14);
doc->setDefaultFont(myfont);
QTextCursor cursor(editor->textCursor());
cursor.insertBlock();
//QTextFragment 片段1 ,
//首次定义文本字符格式 charFormat变量
QTextCharFormat chf;
chf.setForeground(Qt::darkCyan);
//当前文本光标设置字符格式
cursor.setCharFormat(chf);
cursor.insertText("first sentence1111111");
//QTextFragment 片段2 ,换一种字体颜色 红色
//修改 QTextCharFormat 对象
chf.setForeground(Qt::red);
cursor.setCharFormat(chf);
cursor.insertText("second sentence2222The QTextBlock class provides a container for text fragments in a QTextDocument.");
// ---注意下面这行代码,如果注释掉,这3个fragment就是一个整block
// ----如果不注释掉,那么百度超链接就是一个独立的块,打印结果只有百度
//cursor.insertBlock();
//第三次定义 QTextCharFormat 字符格式的超链接的使用,字体颜色改成绿色
chf.setForeground(Qt::green);
chf.setAnchor(true); //启用锚功能
chf.setAnchorHref("http://www.baidu.com"); //超链接地址
chf.setBackground(QColor(120,170,200)); //字体背景
chf.setFontUnderline(true); //设置下划线
cursor.setCharFormat(chf);
cursor.insertText("this is to baidu Anchor");
QTextBlock::iterator it;
for (it = cursor.block().begin(); !(it.atEnd()); ++it) {
QTextFragment frag = it.fragment();
if (frag.isValid()) {
if(frag.charFormat().isAnchor()){
qDebug()<<"find anchor";
qDebug()<<frag.text() << frag.charFormat().anchorHref();
}
else{
qDebug() <<"未找到超链接";
qDebug() <<frag.text() ;
}
}
}
}
Widget::~Widget()
{
delete ui;
}
效果图:
qDebug打印结果:
未找到超链接
"first sentence1111111"
未找到超链接
"second sentence2222The QTextBlock class provides a container for text fragments in a QTextDocument."
find anchor
"this is to baidu Anchor" "http://www.baidu.com"
原文代码Qt 富文本处理(10):文本片段和文本字符格式_qtextcharformat-CSDN博客
2.2 QTextFragment构造函数
QTextFragment(const QTextFragment &other)
QTextFragment()
3. QTextDocumentFragment Class
一段富文本的片段。可以插入QTextDocument。 这个片段可以从QTextDocument中创建,可以从QTextCursor 选择,或者从另一个片段拷贝构造。还可以被静态函数创建,这两个函数是fromPlainText() and fromHtml().
暂时还不知道有什么用处
QTextFragment和 QTextDocumentFragment可以混合在一起
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//the whole size
resize(900,700);
//CSDN
QTextEdit *editor = new QTextEdit(this);
//my change it bigger 设置自己的偏好字体
editor->resize(850,650);
QTextDocument *doc = editor->document(); //获取文本文档
QFont myfont("Bahnschrift",14);
doc->setDefaultFont(myfont);
QTextCursor cursor(editor->textCursor());
cursor.insertBlock();
//首次定义文本字符格式 charFormat变量
QTextCharFormat chf;
//然后插入新片段
chf.setBackground(QColor(100,190,200));
cursor.setCharFormat(chf);
cursor.insertText("this is QTextFragment hello world hello worldhello worldhello worldhello worldhello world");
QString str222=cursor.selectedText();
QTextDocumentFragment docfrag2= QTextDocumentFragment ::fromHtml("<h2>this is QTextDocumentFragment HTML 5 new attributes </h2>");
cursor.insertFragment(docfrag2);
}
Widget::~Widget()
{
delete ui;
}
3.1 构造函数
3.1.1拷贝构造函数和 等号赋值重载 operator =
3.1.2 空的 QTextDocumentFragment()
3.1.3 QTextDocumentFragment(const QTextDocument *document)
3.1.4 QTextDocumentFragment(const QTextCursor &cursor)
第 3 、 4种还没有找到相应代码
3.2 插入文本片段
void QTextCursor::insertFragment(const QTextDocumentFragment &fragment)
QTextDocumentFragment docfrag2= QTextDocumentFragment ::fromHtml("<h2>this is QTextDocumentFragment HTML 5 new attributes </h2>");
cursor.insertFragment(docfrag2);
3.3 从光标接口获得文档片段
QTextDocumentFragment docfrag=cursor.selection();
一般来说刚打开,肯定用户什么文字都没有选择,所以这个方法一般用在鼠标拖拽选中的事件里?
QTextDocumentFragment docfrag=cursor.selection();
if(docfrag.isEmpty()){
qDebug()<<"selecet nothing ";
}
else{
qDebug()<<str222;
}
4. QTextFrame Class
文档框架为文档正文提供结构。作为文档元素的一般性的容器,创建方式通常是QTextCursor::insertFrame()。
框架可以为富文本构建层级结构。一个document有一个根框架,然后每个框架都有一个父框架和所有子框架的列表(这个列表可能是空的)。也就是说除了根框架,所有frame都有父。
根框架获取方法:QTextDocument::rootFrame()
注意事项:插入一个框架后,光标就在这个框架里面,再进行操作就必须重置光标位置,到这个框架的后面去,不然会出现这种情况:
(代码地址https://github.com/zzzcb/qt/commit/c315df70689bc55193ca0de0783bd5356c305a07#diff-ffd4b1d3349d0eb2c42f7240386e34bc9caaded91547c37a59499ccdbecc3b8d
还不太会用github,进去主页右上角搜索框,先输入一个 / 再输入你想搜索的主题如QTextFrame回车 这里摘抄了部分代码)
代码如下:
QTextFrameFormat fmt;
fmt.setBackground(Qt::green);
fmt.setMargin(1);
fmt.setBorder(1);
fmt.setPadding(2);
fmt.setWidth(QTextLength(QTextLength::PercentageLength, 45));
fmt.setPosition(QTextFrameFormat::FloatLeft);
cursor.insertFrame(fmt);
cursor.insertBlock();
cursor.insertText("Showing 9 changed files with 359 additions and 0 deletions.");
QTextFrameFormat fmt2;
fmt2.setBackground(QColor(180,142,120));
fmt2.setMargin(1);
fmt2.setBorder(3);
fmt2.setPadding(2);
fmt2.setWidth(QTextLength(QTextLength::PercentageLength, 45));
fmt2.setPosition(QTextFrameFormat::FloatRight);
cursor.insertFrame(fmt2);
cursor.insertBlock();
cursor.insertText("Showing 9 changed files with 359 additions and 0 deletions.");
所以,更正方法,是在设定第二个frameFormat fm2前面,添加两行代码
QTextFrame *myroot=doc->rootFrame();
cursor=myroot->lastCursorPosition();
然后就由框架相互嵌套,变成平等关系:
4.1 QTextFrame::iterator class
一个框架中至少包含一个块 block ,可能还有子框架。所以框架的迭代器可能找到的是一个文本块,也可能是框架,加入判断条件后,就可以进行下一步操作。迭代器找到的第一个元素是begin(),最后一个元素是 end().(注意,迭代器是只读的,不能改变任何内容)。
迭代器的一些重要方法:
QTextBlock currentBlock() const
QTextFrame * currentFrame() const
QTextFrame * parentFrame() const
案例:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//the whole size
resize(900,700);
//CSDN
QTextEdit *editor = new QTextEdit(this);
//my change it bigger 设置自己的偏好字体
editor->resize(850,650);
QTextDocument *doc = editor->document(); //获取文本文档
QFont myfont("Bahnschrift",14);
doc->setDefaultFont(myfont);
QTextCursor cursor(editor->textCursor());
cursor.insertBlock();
//首次定义文本字符格式 charFormat变量
QTextCharFormat chf;
//第四次定义 然后插入新片段
chf.setBackground(QColor(100,190,200));
cursor.setCharFormat(chf);
cursor.insertText("this is QTextFragment hello world hello worldhello worldhello worldhello worldhello world");
QString str222=cursor.selectedText();
QTextDocumentFragment docfrag2= QTextDocumentFragment ::fromHtml("<h2>this is QTextDocumentFragment HTML 5 new attributes </h2>");
cursor.insertFragment(docfrag2);
QTextFrameFormat fmt;
fmt.setBackground(Qt::green);
fmt.setMargin(1);
fmt.setBorder(1);
fmt.setPadding(2);
fmt.setWidth(QTextLength(QTextLength::PercentageLength, 45));
fmt.setPosition(QTextFrameFormat::FloatLeft);
cursor.insertFrame(fmt);
cursor.insertBlock();//这句话有没有都行,不影响打印结果
cursor.insertText("We've combined the power of the Following feed with the For you feed so there’s one ");
//其实默认就是这句话 所以要改,不能让新框架在旧框架里面
//cursor=frame1->lastCursorPosition();
QTextFrame *myroot=doc->rootFrame();
cursor=myroot->lastCursorPosition();
QTextFrameFormat fmt2;
fmt2.setBackground(QColor(180,142,120));
fmt2.setMargin(1);
fmt2.setBorder(3);
fmt2.setPadding(2);
fmt2.setWidth(QTextLength(QTextLength::PercentageLength, 45));
fmt2.setPosition(QTextFrameFormat::FloatRight);
cursor.insertFrame(fmt2);
cursor.insertBlock();//这句话有没有都行,不影响打印结果
cursor.insertText("Showing 9 changed files with 359 additions and 0 deletions.");
//自己改写,从根框架开始便利
for (QTextFrame::iterator it = myroot->begin(); !(it.atEnd()); it++){
QTextBlock curBlock = it.currentBlock();
QTextFrame * curFrame = it.currentFrame();
if (curBlock.isValid() && !(curBlock.text().isEmpty())){
qDebug()<<"根框架的内部找到的文本块";
qDebug()<< curBlock.text();
}
else if (curFrame){
qDebug()<<"find a frame ";
for (QTextFrame::iterator it2 = curFrame->begin(); !(it2.atEnd()); it2++){
QTextBlock grandcBlock = it2.currentBlock();
QTextFrame * grandcFrame = it2.currentFrame();
if (grandcBlock.isValid() && (!grandcBlock.text().isEmpty())){
qDebug()<<"this is grandBLOCK in child frame ";
qDebug()<< grandcBlock.text();
}
else if(grandcFrame){
qDebug() <<"this is GrandFrame in child frame " ;
}
}
}
}
}
Widget::~Widget()
{
delete ui;
}
效果
打印结果:
根框架的内部找到的文本块
"this is QTextFragment hello world hello worldhello worldhello worldhello worldhello worldthis is QTextDocumentFragment HTML 5 new attributes "
find a frame
this is grandBLOCK in child frame
"We've combined the power of the Following feed with the For you feed so there’s one "
find a frame
this is grandBLOCK in child frame
"Showing 9 changed files with 359 additions and 0 deletions."
综上,qtextFragment 和qtextDocumentFragment 会被认为是一个整块,(反正一个单独的片段是不会被当做一个完整block的 ),然后找到了绿色的frame ,又在里面找到了子块,最后找到咖啡色frame, 在里面又发现子块。
4.2 QTextFrameFormat class
描述框架格式的类。
注意这两个方法都可以使用,第二个更方便
[protected] void QTextObject::setFormat(const QTextFormat &format)
void QTextFrame::setFrameFormat(const QTextFrameFormat &format)
4.3 QTextTable --表格。是 QTextFrame的子类。
不放图片了。首先将鼠标移动到 文档的最前面,在后面插入表格,表格的背景容易和大小不匹配。
cursor.movePosition(QTextCursor::Start);
QTextTableFormat mytablef;
mytablef.setBorderCollapse(false);
QBrush tablebrush(QColor(110,190,220));
// mytablef.setHeight(60);
// mytablef.setWidth(200);
//写浮点数,固定了大小。但是容易跟背景出现距离上的偏差。
mytablef.setWidth(QTextLength(QTextLength::PercentageLength,45));
mytablef.setHeight(QTextLength(QTextLength::PercentageLength,20));
mytablef.setHeaderRowCount(1);
mytablef.setBackground(tablebrush);
QTextTable *mytable = cursor.insertTable(3,3,mytablef);
//更改单个单元格的格式,注意 从0开始数,第0行第0列是我们看起来第一个单元格。
QTextTableCell cell = mytable->cellAt(1, 1);
//注意,单元格的setFormat设置的是字符格式charFormat 也就是填写到这个单元格的字体格式。
QTextCharFormat format = cell.format();
format.setBackground(Qt::blue);
cell.setFormat(format);
//输入几个字,发现单元格的宽度会跟着你输入的字而变化。
//这个目前还没找到办法
4.3.1 QTextTableFormat Class
代码如上。
4.3.2 QTextTableCell Class
单元格类代表某个单元格的一些特性。例如所在的行(int ) ,所在的列 ( int ) ,单元格的字符格式charFormat , 背景颜色等等。
4.3.3 QTextTableCellFormat Class
5.QTextList
5.1 QTextListFormat
6.总结
6.1 文档元素之间的关系
QTextDocument.
QTextBlock ,
QTextFragment,
QTextDocumentFragment ,
QTextframe ,
QTextFragment是 块的片段,但是里面能装的东西和块一样,里面能包含text文本,表格,列表,图片。
6.2 迭代器有哪些种类,各有什么用途
QTextDocument:: iterator 找到的只有block , it.begin() 是第一个块,it.end() 是最后一个块
QTextFrame:: iterator 能找到框架内的子块,也能找到子框架。
QTextBlock::iterator 找到的是QTextFragment
以下代码摘抄自
【Qt】富文本框架(一、富文本文档)_qt富文本控件_卡钦斯基的博客-CSDN博客
QTextBlock currentBlock = textDocument->begin();
while (currentBlock.isValid()) {
processBlock(currentBlock);
currentBlock = currentBlock.next();
}
7. 其他相关的类
7.1 QTextLength
7.2 QFontMetrics