- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
word 上的字体可以更改,变换颜色等的是rich text 富文本
而window记事本那种是纯文本(plain text)
关于它的帮助可以看助手 Rich Text Processing 关键字查找
QT对富文本的处理只有只读
和编辑
二种方式
对于文档的读取和编辑要使用二种不同的接口
文档的光标
主要基于QTextCursor类
,而文档的框架
主要基于QTextDocument类
。
一个富文本文档的结构分为几种元素来表示,分别是框架(QTextFrame)
、文本块(QTextBlock)
、表格(QTextTable)
和列表(QTextList)
。
每种元素的格式又使用相应的 format类
来表示,分别是框架格式(QTextFrameFormat)
、文本块格式(QTextBlockFormat)
,表格格式(QTextTableFormat)
和列表格式(QTextListFormat)
,这些格式一般在编辑文档时使用,所以常和QTextCursor类
配合使用。
QTextEdit类
就是一个富文本编辑器,所以在构造QTexrEdit类
的对象时就已经构建了一个QTextDocument类对象
和一个QTextCursor类对象
,只须调用它们进行相应的操作即可
一个空的文档包含了一个根框架(Root frame)
,这个根框架又包含了一个空的文本块(Block)。
框架将一个文档分为多个部分,在根框架里可以再添加文本块、子框架和表格等,一个文档的结构如图所示
下面实际写下:
新建Qt Widget项目,名称myrichtext ,基类QMainWindow
打开ui界面,拖入一个Text Edit 部件。然后到mainwindow.cpp中
先添加头文件#include <QTextFrame>
再在MainWindow构造函数中添加如下代码
QTextDocument *document = ui->textEdit->document(); // 获取文档对象
QTextFrame *rootFrame = document->rootFrame(); // 获取根框架
QTextFrameFormat format; // 创建框架格式
format.setBorderBrush(Qt::red); // 边界颜色
format.setBorder(3); // 边界宽度
rootFrame->setFrameFormat(format); // 框架使用格式
在构造函数中创建文档对象获取了编辑器文档内容,创建了根框架,并且设置好了框架的格式
现在运行程序
这里还可以使用setHeight()和setWidth()函数来固定高度和宽度
下面继续添加代码,使用光标类对象,在根框中再添加一个子框架:
QTextFrameFormat frameFormat;
frameFormat.setBackground(Qt::lightGray); // 设置背景颜色
frameFormat.setMargin(10); // 设置边距
frameFormat.setPadding(5); // 设置填衬
frameFormat.setBorder(2);
frameFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Dotted); // 设置边框样式
QTextCursor cursor = ui->textEdit->textCursor(); // 获取光标
cursor.insertFrame(frameFormat); // 在光标处插入框架
这里又建立了一个框架格式,然后获取了光标,在光标处插入框架
这里为框架格式设置了边白,它分为边界内与本身内容间的空白,即填衬(Padding) ,和边界外与其他内容间的空白,即边距(Margin)。框架边界的样式有实线,点线等。框架格式的属性如图5-10所示。现在可以运行程序查看效果。
文本块QTextBlock类为文本文档QTextDocument提供了一个文本片段(QText-Fragment)的容器。
下面通过例子理解它:
继续在前面的项目中添加代码。在mainwindow.h文件中添加私有槽的声明:
private slots:
void showTextFrame(); //遍历文档框架
然后再mainwinodw…cpp构造函数中实现槽
#include <QDebug>
QAction *action_textFrame = new QAction(tr("框架"), this);
connect(action_textFrameA,&QAction::triggered,this,&MainWindow::showTextFrame);
ui->mainToolBar->addAction(action_textFrame); // 在工具栏添加动作
这里新建一个工具栏动作,触发信号后实现showTextFrame函数
下面实现槽函数的功能
void MainWindow::showTextFrame() // 遍历框架
{
QTextDocument *document = ui->textEdit->document();
QTextFrame *frame = document->rootFrame();
QTextFrame::iterator it; // 建立QTextFrame类的迭代器
for (it = frame->begin(); !(it.atEnd()); ++it) {
QTextFrame *childFrame = it.currentFrame(); // 获取当前框架的指针
QTextBlock childBlock = it.currentBlock(); // 获取当前文本块
if (childFrame)
qDebug() << "frame";
else if (childBlock.isValid())
qDebug() << "block:" << childBlock.text();
}
}
在这个函数中获取了文档的根框架,然后使用它的迭代器iterator(遍历器)来遍历根框架中的所有子框架和文本块。
在循环语句中先使用QTextFrame
类的 begin()
函数使iterator指向根框架最开始的元素,然后使用iterator的 atEnd()
函数判断是否已经到达了根框架的最后一个元素。
这里如果出现子框架,则输出一个框架的提示;如果出现文本块,则输出文本块提示和文本块的内容。
现在运行程序,然后在编辑器中输入一些内容,按下工具栏中的“框架”动作,查看一下输出栏中的信息,如图
只输出了根框架的文本块。
下面使用其他方法来遍历全部文本块
下面再mainwindow.h文件中继续添加私有槽private slots声明:
void showTextBlock(); //遍历所有文本块
然后与上面相同,先建立动作
QAction *action_textBlock = new QAction(tr("文本块"), this);
connect(action_textBlock, &QAction::triggered, this, &MainWindow::showTextBlock);
ui->mainToolBar->addAction(action_textBlock);
添加槽函数showTextBlock
void MainWindow::showTextBlock() // 遍历文本块
{
QTextDocument *document = ui->textEdit->document();
QTextBlock block = document->firstBlock(); // 获取文档的第一个文本块
for (int i = 0; i < document->blockCount(); i++) {
qDebug() << tr("文本块%1,文本块首行行号为:%2,长度为:%3,内容为:")
.arg(i).arg(block.firstLineNumber()).arg(block.length())
<< block.text();
block = block.next(); // 获取下一个文本块
}
}
这里使用QTextDocument
类的firstBlock()
函数来获取文档的第一个文本块,而blockCount()
函数可以获取文档中所有文本块的个数,这样便可以使用循环语句来遍历所有文本块。
每一个文本块都输出了编号、第一行行号、长度和内容,然后使用QTextBlock
的next()
函数来获取下一个文本块。
这里需要说明的是, tr()函数中使用“%1”等位置标记,然后在后面使用arg()
添加变量作为参数,这样这些参数就会代替前面字符串中的“%1”显示出来。字符串中有几个“%”号,后面就应该有几个arg()
与其对应。
arg()
是 QString类中的函数,因为 tr()
函数返回QString类对象,所以这里可以这样使用。
现在运行程序,然后在编辑器中添加一些内容,按下“文本块”动作查看效果。
可以看到,行号是从0
开始标记的,而且如果不使用回车换行,那么它即便在编辑器中显示在了第二行,其实还是在一个文本块里。
文本块的长度是从1
开始计算的,就是说,就算什么都不写,那么文本块的长度也是1
,所以长度会比实际字符数多1
。
下面试试如何更改文本块文字格式
在mainwindow.h文件中添加私有槽声明
void setTextFont(bool checked); //设置字体格式
然后在mainwindow.cpp构造函数中创建动作
QAction *action_font = new QAction(tr("字体"), this);
action_font->setCheckable(true); // 设置动作可以被选中
connect(action_font, &QAction::toggled, this, &MainWindow::setTextFont);
ui->mainToolBar->addAction(action_font);
实现槽函数
void MainWindow::setTextFont(bool checked) // 设置字体格式
{
if(checked){ // 如果处于选中状态
QTextCursor cursor = ui->textEdit->textCursor();
QTextBlockFormat blockFormat; // 文本块格式
blockFormat.setAlignment(Qt::AlignCenter); // 水平居中
cursor.insertBlock(blockFormat); // 使用文本块格式
QTextCharFormat charFormat; // 字符格式
charFormat.setBackground(Qt::lightGray); // 背景色
charFormat.setForeground(Qt::blue); // 字体颜色
// 使用宋体,12号,加粗,倾斜
charFormat.setFont(QFont(tr("宋体"), 12, QFont::Bold, true));
charFormat.setFontUnderline(true); // 使用下划线
cursor.setCharFormat(charFormat); // 使用字符格式
cursor.insertText(tr("测试字体")); // 插入文本
}
else{/*恢复默认的字体格式*/} // 如果处于非选中状态,可以进行其他操作
}
这里先获得了编辑器的光标,然后为其添加了文本块格式和字符格式。文本块格式主要设置对齐方式,缩进等格式,字符格式主要设置字体、颜色、下划线等格式。最后使用光标插人了一个测试文字。
设置字体格式运行效果
下面看一下怎样在编辑器中插入表格和图片。
在mianwindow.h文件中添加槽 声明
void showTextFrame(); // 遍历文档框架
void showTextBlock(); // 遍历所有文本块
void setTextFont(bool checked); // 设置字体格式
然后到mainwindow.cpp文件的构造函数中继续添加
void insertTable(); // 插入表格
void insertList(); // 插入列表
void insertImage(); // 插入图片
然后到mainwindow.cpp构造函数中继续添加动作
QAction *action_textTable = new QAction(tr("表格"),this);
QAction *action_textList = new QAction(tr("列表"),this);
QAction *action_textImage = new QAction(tr("图片"),this);
connect(action_textTable, &QAction::triggered, this, &MainWindow::insertTable);
connect(action_textList, &QAction::triggered, this, &MainWindow::insertList);
connect(action_textImage, &QAction::triggered, this, &MainWindow::insertImage);
ui->mainToolBar->addAction(action_textTable);
ui->mainToolBar->addAction(action_textList);
ui->mainToolBar->addAction(action_textImage);
三个动作,添加到工具栏中,下面定义槽函数
void MainWindow::insertTable() // 插入表格
{
QTextCursor cursor = ui->textEdit->textCursor();
QTextTableFormat format; // 表格格式
format.setCellSpacing(2); // 表格外边白
format.setCellPadding(10); // 表格内边白
cursor.insertTable(2, 2, format); // 插入2行2列表格
}
void MainWindow::insertList() // 插入列表
{
QTextListFormat format; // 列表格式
format.setStyle(QTextListFormat::ListDecimal); // 数字编号
ui->textEdit->textCursor().insertList(format);
}
void MainWindow::insertImage() // 插入图片
{
QTextImageFormat format; // 图片格式
format.setName("../myrichtext/logo.png"); // 图片路径
ui->textEdit->textCursor().insertImage(format);
}
表格和列表的遍历可以用QTextFrame::iterator来遍历
可以通过Rich Document Structure 关键字查看
QTextEdit类提供了很多方便的函数,比如常用的复制粘贴等等
下面主要介绍比较难的查找功能 find()
在前面的代码中,在mainwindow.h中添加类的前置声明
class QLineEdit;
class QDialog;
然后添加私有对象指针
private:
QLineEdit *lineEdit;
QDialog *findDialog;
在添加私有槽声明private slots
void textFind(); // 查找文本
void findNext(); // 查找下一个
在mainwindow.cpp构造函数中实现动作创建
先添加头文件:
#include <QDebug>
#include <QLineEdit>
#include <QDialog>
#include <QPushButton>
#include <QVBoxLayout>
QAction *action_textFind = new QAction(tr("查找"), this);
connect(action_textFind, &QAction::triggered, this, &MainWindow::textFind);
ui->mainToolBar->addAction(action_textFind);
在实现QLineEdit行编辑器和QDialog对话框创建界面
findDialog = new QDialog(this); // 创建对话框
lineEdit = new QLineEdit(findDialog); // 创建行编辑器
QPushButton *btn = new QPushButton(findDialog); // 创建按钮
btn->setText(tr("查找下一个"));
connect(btn, &QPushButton::clicked, this, &MainWindow::findNext); // 按钮按下,findnext
QVBoxLayout *layout = new QVBoxLayout; // 创建垂直布局管理器
layout->addWidget(lineEdit); // 添加部件
layout->addWidget(btn);
findDialog->setLayout(layout); // 在对话框中使用布局管理器
实现槽函数
void MainWindow::textFind() // 查找文本
{
findDialog->show();
}
void MainWindow::findNext() // 查找下一个
{
QString string = lineEdit->text();
// 使用查找函数查找指定字符串,查找方式为向后查找
bool isfind = ui->textEdit->find(string, QTextDocument::FindBackward);
if(isfind){ // 如果查找成功,输出字符串所在行和列的编号
qDebug() << tr("行号:%1 列号:%2")
.arg(ui->textEdit->textCursor().blockNumber())
.arg(ui->textEdit->textCursor().columnNumber());
}
}
这里使用了find函数
进行查找。选项QTextDocument::FindBackward
表示向后查找,默认向前查找;还有FindWholeWords,FindCaseSensitively
其实find函数只是为了方便使用,更多的查找功能可以使用QTextDocument类的find函数。
使用QSyntaxHighlighter类,创建子类,实现highlightBlock函数,使用时候直接将QTextDocument类对象指针作为父部件指针,这样就可以自动调用highlightBlock()函数。
首先在项目中添加新文件,模板选择C++ Class,相当于.h文件,命名mysyntaxhighlighter.h
#ifndef MYSYNTAXHIGHLIGHTER_H
#define MYSYNTAXHIGHLIGHTER_H
#include <QSyntaxHighlighter>
class MySyntaxHighlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
explicit MySyntaxHighlighter(QTextDocument *parent = 0);
protected:
void highlightBlock(const QString &text); //必须重新实现该函数
};
#endif // MYSYNTAXHIGHLIGHTER_H
现在到mysyntaxhighlighter.cpp文件中,先更改构造函数为:
#include "mysyntaxhighlighter.h"
MySyntaxHighlighter::MySyntaxHighlighter(QTextDocument *parent) :
QSyntaxHighlighter(parent)
{
}
然后添加highlightBlock()函数定义:
void MySyntaxHighlighter::highlightBlock(const QString &text) // 高亮文本块
{
QTextCharFormat myFormat; // 字符格式
myFormat.setFontWeight(QFont::Bold);
myFormat.setForeground(Qt::green);
QString pattern = "\\bchar\\b"; // 要匹配的字符,这里是“char”单词
QRegExp expression(pattern); // 创建正则表达式
int index = text.indexOf(expression); // 从位置0开始匹配字符串
// 如果匹配成功,那么返回值为字符串的起始位置,它大于或等于0
while (index >= 0) {
int length = expression.matchedLength(); // 要匹配字符串的长度
setFormat(index, length, myFormat); // 对要匹配的字符串设置格式
index = text.indexOf(expression, index + length); // 继续匹配
}
}
这里主要使用了正则表达式和QString类
的indexOf()
函数来进行字符串匹配,如果匹配成功,则使用QSyntaxHighlighter类
的setFormat()函数
来设置字符格式。
下面来使用这个类
在 mainwindow.h 文件中添加类的前置声明:
class MySyntaxHighlighter;
然后再添加私有对象指针:MySyntaxHighlighter * highlighter;
到mainwindow.cpp文件中添加头文件:#include"mysyntaxhighlighter.h"
然后在构造函数的最后添加一行代码:highlighter = new MySyntaxHighlighter(ui->textEdit->document());
这里创建了MySyntaxHighlighter类的对象,并且使用编辑器的文档对象指针作其参数
现在运行运行程序,输入“char”查看一下效果。
只有char时候高亮,匹配表达式
关于语法高亮,可以查看Syntax Highlighter Example示例程序。
在富文本处理中还提供了对 HTML子集的支持,可以在QLabel或者QTextEdit添加文本时使用HTML标签或者CSS属性,具体内容可以在帮助中通过Supported HTMIL Subset
关键字查看,下面举一个最简单的例子。
在 mainwindow.cpp文件中的构造函数最后添加下面一行代码:
ui->textEdit->append(tr("<h1 ><font color = red>使用HTLM </font ></h1>"));
这里往编辑器中添加了文本,并且使用了HTMI标签,运行程序查看效果。
前面讲到了在编辑器中使用语法高亮,那么读者可能会想到在编辑代码时另一个非常有用的功能,就是自动补全。
Qt中提供了QCompleter
类来实现自动补全,这个类在第3章介绍行编辑器时已经介绍过了,可以使用它来实现编辑器中的自动补全功能。这个可以参考示例程序Custom Completer。
富文本处理的内容就讲到这里,其涉及的东西很多,要学好这些内容就要多动手去编写程序。帮助文档的Advanced RichText
Processing里还提供了一个处理大文档的方法,需要的读者可以进行参考。对于这部分内容,可以查看Text
Edit程序,这个例子是一个综合的富文本编辑器。
表架构 DROP TABLE bla; CREATE TABLE bla (id INTEGER, city INTEGER, year_ INTEGER, month_ INTEGER, val I
我需要拆分字符串/或从具有以下结构的字符串中获取更容易的子字符串。 字符串将来自 window.location.pathname 或 window.location.href,看起来像 text/n
每当将对象添加到数组中时,我都会尝试更新 TextView ,并在 TextView 中显示该文本,如下所示: "object 1" "object 2" 问题是,每次将新对象添加到数组时,它都会覆盖
我目前正在寻找使用 Java 读取网站可见文本并将其存储为纯文本字符串的方法。 换句话说,我想转换成这样: Hello stupid World进入“ Hello World ” 或者类似的东西 Un
我正在尝试以文本和 HTML 格式发送电子邮件,但无法正确发送正确的 header 。特别是,我想设置 Content-Type header ,但我找不到如何为 html 和文本部分单独设置它。 这
我尝试了上面的代码,但我无法绑定(bind)文本,我怎样才能将资源内部文本 bloc
我刚刚完成了 Space Shooter 教程,由于没有 GUIText 对象,所以我创建了 UI.Text 对象并进行了相应的编码。它在统一播放器中有效,但在构建 Web 应用程序后无效。我花了一段
我有这个代码: - (IBAction)setButtonPressed:(id)sender { NSUserDefaults *sharedDefaults = [[NSUserDefau
抱歉标题含糊不清,但我想不出我想在标题中做什么。无论如何,对于图像上的文本,我使用了 JLabel 文本并将其添加到图标中。 JLabel icon = new JLabel(new Imag
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我在将 Twitter 嵌入到我从 HTML 5 转换的 wordpress 运行网站时遇到问题。 我遇到的问题是推文不是我的自定义字体... 这是我无法使用任何 css 定位的 HTML 代码,我正
我正在尝试找到解决由于使用以下形式的代码而导致的冗余字符串连接问题的最佳方法: logger.debug("Entering loop, arg is: " + arg) // @1 在大多数情况下,
我写了这个测试 @Test public void removeRequestTextFromRouteError() throws Exception { String input = "F
我目前正在创建一个正则表达式来拆分所有匹配以下格式的字符串:&[文本],并且需要获取文本。字符串可能类似于:something &[text] &[text] everything &[text] 等
有没有办法将标题文本从一个词变形为另一个词,同时保留两个词中使用的字母?我看过的许多 css 文本动画大多是视觉的,很少有旋转整个单词的。 我想要做的是从一个词过渡,例如“BEACH”到“CHANGE
总结matplotlib绘图如何设置坐标轴刻度大小和刻度。 上代码: ?
我在容器 (1) 中创建了容器 (2)。你能帮忙如何向容器(1)添加文本吗?下面是我的代码 return Scaffold( body: Padding( padding: c
我似乎找不到任何人或任何人这样做过。我试图限制我们使用的图像数量,并想创建一个带有渐变作为其“颜色”的文本,并在其周围设置渐变轮廓/描边 到目前为止,我还没有看到任何将两者结合在一起的东西。 我可以自
我正在为视频游戏暗黑破坏神 2 使用 discord.py 构建一个不和谐机器人。其中一项功能要求机器人从暗黑破坏神 2 屏幕截图中提取项目的名称和属性。我目前正在为此使用 pytesseract,但
我很难弄清楚如何旋转 strip.text theme 中的属性来自 ggplot2 .我使用的是 R 版本 3.4.2 和 ggplot2 版本 2.2.1。 以下是 MWE 的数据。 > dput
我是一名优秀的程序员,十分优秀!