写点什么

Qt 实现文本编辑器(二)

  • 2022 年 9 月 13 日
    河北
  • 本文字数:3521 字

    阅读完需:约 12 分钟

Qt实现文本编辑器(二)

上一章节讲述了如何制作文本编辑页面,以及应该有哪些功能需要实现,只是做了展示效果,实际的点击事件并没有处理。今天来具体讲解下是如何实现菜单栏以及工具栏上对应的需求吧~

功能实现

功能:

1、动作消息触发

2、具体功能:打开文件、新建文件、复制、剪切、粘贴

3、文本编辑功能:字体设置

今天只讲述以上三大功能,至于:旋转、缩放等功能都是针对于图片来说的,等下一章节,具体的讲解方式就不在是文本编辑器的功能了,静待后续更文吧!

功能 1:动作消息

上一章节的动作已经创建完成了,那么该如何触发这些动作呢?

在 Qt 中动作触发方式与控件触发方式是一致的,例如:想要让一个按钮控件响应操作,需要响应 QPushButton::clicked 消息,这里也是同样的道理。

想要响应动作事件用到的是 QAction::triggered。

各个动作对应的槽函数如下

打开文件

connect(m_pActionOpenFile, &QAction::triggered, this, &QtTextEditor::OnTriggeredOpenFile);
复制代码

新建文件

connect(m_pActionOpenFile, &QAction::triggered, this, &QtTextEditor::OnTriggeredNewFile);
复制代码

复制、剪切、粘贴

connect(m_pActionOpenFile, &QAction::triggered, m_editContent, &QTextEdit::copy);
connect(m_pActionOpenFile, &QAction::triggered, m_editContent, &QTextEdit::cut);
connect(m_pActionOpenFile, &QAction::triggered, m_editContent, &QTextEdit::paste);
复制代码

看到槽函数,大家可以发现,对于复制、剪切、粘贴功能都是采用 QTextEdit 控件实现的,在这里不需要做新的处理,直接使用父类消息就可以了。


为了对编辑文本类的功能处理,最好的方式继承自 QTextEdit 进行功能封装,假设叫做:QMyTextEdit,后续都用该类作为编辑文本类

功能 2:动作事件实现

针对上述两个需要自己实现的槽函数响应,接下来就进行详细的讲述吧~

2.1:打开文件

打开文件,代表的是打开一个已经存在的文件,这里需要用到 QFileDialog 类,使用 QFileDialog::getOpenFileName()静态函数,返回选择文件的带路径的完整路径名。

void QtTextEditor::OnTriggeredOpenFile(){	QString qsFileName = QFileDialog::getOpenFileName(this);	if (qsFileName.isEmpty())	{		return;	}	if (m_editContent->document()->isEmpty())	{		this->LoadFileContent(m_editContent, qsFileName);	}	else	{		QMyTextEdit *editContent = new QMyTextEdit;		editContent->show();		this->LoadFileContent(editContent, qsFileName);		m_vetEditCtrls.push_back(editContent);	}}
复制代码

代码思路:

获取打开的文件路径,如果返回的字符串是空,说明未打开有效文件,不进行处理;

在展示内容之前,判断当前 edit 控件是否有数据?如果没有直接在当前文本编辑控件中展示;

如果当前文本编辑控件存在数据,则重新创建一个 QMyTextEdit 自定义类,用来展示新内容。

其中,LoadFileContent 函数的具体内容:

void QtTextEditor::LoadFileContent(QMyTextEdit* editCtrls, QString qsFileName){	QFile file(qsFileName);	if (file.open(QIODevice::ReadOnly | QIODevice::Text))	{		QTextStream textStream(&file);		while (!textStream.atEnd())		{			editCtrls->append(textStream.readLine());		}	}}
复制代码

代码说明:

采用了 QTextStream 方式读取文件流数据,可以方便的读写单词、行和数字,甚至还提供了填充、对齐和数字格式化的选项操作。

为什么第一个参数会传入类指针呢?

因为在这里有个功能,叫做新建,在读取文件的时候,假设当前展示的文本编辑器类 QMyEdit 中存在了内容时,是需要重新创建的,为了统一起见,将第一个参数设置为类指针,方便函数调用。

无论是新创建的页面还是已经存在的页面都可以进行写入文本。

2.2:新建文件

在这里所谓的新建就是建立一个空白的编辑文本,功能简单,这里就不再过多说明了。

void QtTextEditor::OnTriggeredNewFile(){	QMyTextEdit *editCtrls = new QMyTextEdit;	editCtrls->show();	m_vetEditCtrls.push_back(editCtrls);}
复制代码

唯一需要提一句的就是:创建了新的文本类之后,一定要记得存储类指针,为了防止在后续使用的过程中查询不到以及在销毁的过程中,防止内存泄漏。

2.3:复制、剪贴、粘贴

这三个功能都沿用的 QTextEdit 自带功能,这里不用再过多说明,直接响应父类消息就可以了。

功能 3:文本编辑

大家都用过文本编辑器,主要的功能还是对文字的操作,那么在这里主要讲述了文字工具栏以及文字的展示风格

3.1 文字工具栏

正如上一章节讲述那般,工具条的使用大家都不陌生了吧,这里需要创建一个字体工具栏,并包含了如下几个功能:

实际做出来的效果,如下:

对于字体的设置,与其它工具条上展示的内容不一致,不再采用动作,而是使用了控件的方式

具体每个功能对应的类名上面的表格已经说明了,重点要说的是:获取字体风格以及字体的大小

字体风格

QFontCombobox 是 QComboBox 的一个子类,是不能被编辑的,只能用来选择字体。

m_ComboFontStyle = new QFontComboBox;m_ComboFontStyle->setFontFilters(QFontComboBox::ScalableFonts);
复制代码

字体字号

采用的是:QFontDatabase,提供了有关底层窗口系统中可用的字体信息,当前主要用来查询字体大小的。

m_ComboFontSize = new QComboBox;QFontDatabase dbFont;foreach(int size, dbFont.standardSizes()){	m_ComboFontSize->addItem(QString::number(size));}
复制代码

代码解析:

这里使用了 foreach 的方式,代替了 for 循环,要是有不懂得小伙伴可以详细查询,这里只是做了解释说明~

standarSizes 函数,返回了可用的标准字号的列表,并将列表内容插入到 QCombobox 中。

另外说明:QToolButton 与 QPushButton 的用法一致,只是换了类名,创建方法以及消息绑定都不再过多说明了。


最后,将创建的这些控件绑定到字体工具条上

m_pToolFont = addToolBar("Font");m_pToolFont->setAllowedAreas(Qt::BottomToolBarArea );m_pToolFont->addWidget(m_labFontStyle);m_pToolFont->addWidget(m_ComboFontStyle);m_pToolFont->addWidget(m_labFontSize);m_pToolFont->addWidget(m_ComboFontSize);m_pToolFont->addSeparator();m_pToolFont->addWidget(m_btnFontBold);m_pToolFont->addWidget(m_btnFontItalic);m_pToolFont->addSeparator();m_pToolFont->addWidget(m_btnFontColor);
复制代码

看到这里,大家可以尝试下自己写的代码,看看是不是可以运行起来。

在这里需要注意的是:为什么运行起来是下面这个样子?

有没有人有这种情况?为什么和第一张效果图不一样呢?不是另起一行,而是什么都看不到了呢?

在 ToolBar 中,如果一行展示不全的情况下,需要告诉 QToolBar 另起一行,则,需要在 addToolBar 之前添加如下代码:

this->addToolBarBreak(Qt::TopToolBarArea);
复制代码

再次运行,就变成了两行的工具栏了,踩坑记录,希望大家也不要犯这个错误啦~

3.2:字体风格

在这里,说到的字体风格无外乎就是工具栏上所展示的内容啦!

文字风格这部分都采用了 QTextCharFormat 对象进行实现的

字体风格

void QtTextEditor::OnComboFontStyle(QString& qsText){	QTextCharFormat fmt;	fmt.setFontFamily(qsText);
QTextCursor cursor = m_editContent->textCursor(); if (!cursor.hasSelection()) { cursor.select(QTextCursor::WordUnderCursor); } cursor.mergeCharFormat(fmt); m_editContent->mergeCurrentCharFormat(fmt);}
复制代码

代码解析:

获取控件的焦点,假设当前控件上的文本并没有被选中,就指定光标区域所在的词为高亮选定词,从而设置字体风格样式

字号

fmt.setFontPointSize(qsText.toInt());
复制代码

加粗

fmt.setFontWeight(bCheck);
复制代码

斜体

fmt.setFontItalic(bchecked);
复制代码

以上几个功能,用法都很类似,正如我前面提到的,都是采用 QTextCharFormat 类,只是设置的函数不同,具体的功能不在做过多说明,下面,与上述几个功能相比较,需要说明的是:颜色设置。

字体颜色

在这时颜色的时候,用到了系统文件类:QColorDialog,与打开文件的方式类似,只是类名不一致

void QtTextEditor::OnToolFontColor(bool bchecked){	QColor color = QColorDialog::getColor(Qt::red, this);	if (color.isValid())	{		QTextCharFormat fmt;		fmt.setForeground(color);		m_editContent->mergeCurrentCharFormat(fmt);	}}
复制代码

根据以上功能,具体的显示效果如下:

总结

到这里,具体的文本风格就讲解完成了,在整个设置过程中,最最重要的类就是:QTextCharFormat。

在代码使用过程中,大家会发现,我一直是对 m_editContent 进行操作的,是滴!


其实是存在新建功能的,这里的新建空白文本的文字处理功能就交给大家啦,这是只是做一个示范例子而已,提前说明下,不是很难,只要掌握了当前处于活跃的 QMyEdit 类指针就可以了。


今天的内容就到这里了,我是中国好公民 st,一名 C++程序猿~

发布于: 刚刚阅读数: 4
用户头像

书山有路勤为径,学海无涯苦作舟 2022.07.01 加入

擅长语言:C++ 涉及语言:Python

评论

发布
暂无评论
Qt实现文本编辑器(二)_c++_中国好公民st_InfoQ写作社区