我是靠谱客的博主 高挑服饰,这篇文章主要介绍QCodeEditor - 基于Qt的代码编辑器,现在分享给大家,希望可以做个参考。

在这里插入图片描述

一 基本介绍

It’s not a project from a Qt example.

这不是qt的示例项目!!!这是开源项目的介绍

QCodeEditor是一个支持自动完成、语法高亮和行号的代码编辑器。
它面向所有想要支持多种语言的人,从编程语言到标记语言,甚至是自定义脚本语言。在目前的状态下,它可以完美地处理上面提到的所有功能,但是还有很多事情需要实现。QCodeEditor是基于 Qt 的QPlainTextEdit,它已经包含一个用于添加语法突出显示和自动完成的接口。

源代码和示例代码下载链接:https://download.csdn.net/download/weixin_42887343/76428055
在这里插入图片描述

二 代码使用

使用编辑器本身非常简单。可以通过QPlainTextEdit在表单中添加 a 并将其提升到kgl::QCodeEditor(请注意,必须将“ include/KGL/Widgets ”添加到INCLUDEPATH变量中并且global include必须选中“ ”复选框)或以编程方式将其添加到形式:

复制代码
1
2
3
4
5
6
using namespace kgl; // ## MainWindow::MainWindow QCodeEditor *editor = new QCodeEditor; setCentralWidget(editor); // or: ui->someLayout->addWidget(editor);

通过使用QCodeEditorDesign该类可以更改编辑器的视觉外观。在下面的示例中,我们假设代码编辑器被多个小部件包围,因此为其添加了边框。我们还修改了外观以具有“深色”风格:

复制代码
1
2
3
4
5
6
7
8
9
10
11
using namespace kgl; // ## MainWindow::MainWindow QCodeEditorDesign design; design.setLineColumnVisible(false); design.setEditorBackColor(0xff333333); design.setEditorTextColor(0xffdddddd); design.setEditorBorderColor(0xff999999); design.setEditorBorder(QMargins(1,1,1,1)); // l t r b editor->setDesign(design);

但是如何实际添加一些语法高亮规则,如上图所示?有两种方法可以做到这一点:以编程方式添加它们或从 XML 文件中提取它们。

以编程方式:

复制代码
1
2
3
4
5
6
7
8
9
10
11
using namespace kgl; // ## MainWindow::MainWindow QList<QSyntaxRule> rules; QSyntaxRule rule; rule.setForeColor(QColor(Qt::blue)); rule.setRegex("\bFoo\b"); rule.setId("Foo"); rules.push_back(rule); editor->setRules(rules);

XML 文件:

复制代码
1
2
3
4
5
6
7
8
9
using namespace kgl; // ## MainWindow::MainWindow QCodeEditorDesign design; // modify design ... QList<QSyntaxRule> rules = QSyntaxRules::loadFromFile(":/rule_cpp.xml", design); editor->setRules(rules); // Note: ':/rule_cpp.xml' refers to the path of a QRC resource

下一章将提供如何创建这些 XML 规则的指南。但首先,我们的编辑器需要一些自动完成关键字:

复制代码
1
2
3
4
// ## MainWindow::MainWindow QStringList keywords = { "printf", "scanf" }; editor->setKeywords(keywords);

如果希望添加图标以暗示关键字是函数/成员/宏/… QStandardItemModel,则需要创建自定义并将其传递给“ QCodeEditor::setKeywordModel(model)”。

三 创建 XML 规则文件

XML 规则文件包含由多个子元素组成的最顶层元素。每个子元素都必须包含正则表达式或关键字列表,所有其他属性都是可选的:

复制代码
1
2
3
4
5
6
7
<rules> <rule> <regex>bFoob</regex> <keywords>foo bar key</keywords> </rule> </rules>

有关所有可用属性的参考,请转到rules_template.xml的 github 页面。QCodeEditor甚至支持包含不止一行的规则。虽然它们对于实现多行注释很有用,但它们也可以用于其他目的。

四 ID的用处

从rules_template.xml中可以看出,规则甚至可以定义自定义 ID。在本节中,我将说明如何使用 ID 以及它们为何如此有用。人们可能已经注意到,静态添加关键字并不是一种好的做法,特别是如果您的语言允许包含其他文件或定义变量。

“onMatch”信号
QCodeEditorHighlighteronMatch只要 a string- 通过正则表达式找到 - 被突出显示,就会发出一个名为 ’ ’ 的信号。这使我们能够检索有string问题的:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// ## MainWindow.h using namespace kgl; class MainWindow : public QMainWindow { Q_OBJECT public: ... private slots: void addMacro(const QSyntaxRule &rule, QString seq, QTextBlock block); private: QMap<QTextBlock, QSyntaxRule> m_RuleMap; QMap<QTextBlock, QString> m_MacroMap; QCodeEditor *m_Editor; }; // ## MainWindow::MainWindow QSyntaxRule defineRule; defineRule.setRegex("(#define\s+)\K(\D\w*)(?=s+S+)"); defineRule.setId("define"); editor->setRules({ defineRule }); connect(m_Editor->highlighter(), SIGNAL(onMatch(QSyntaxRule,QString,QTextBlock)), this, SLOT(addMacro(QSyntaxRule,QString,QTextBlock))); // ## MainWindow::addMacro if (rule.id() == "define") { foreach (const QTextBlock &b, m_RuleMap.keys()) { if (b.userData() != NULL && block.userData() != NULL) { auto *d1 = static_cast<QCodeEditorBlockData *>(block.userData()); auto *d2 = static_cast<QCodeEditorBlockData *>(b.userData()); if (d1->id == d2->id) { return; } } } // Not existing yet; add it QString def = seq.split(' ').at(0); m_RuleMap.insert(block, rule); m_MacroMap.insert(block, def); m_Editor->addKeyword(def); }

这样,可以为自定义类、变量和定义提供自动完成功能,或者包含其他文件并从中导入符号。

“onRemove”信号
删除曾经添加的宏可能有点棘手,因为 QTextBlock 的设计使我们几乎不可能跟踪它。QCodeEditorHighlighter提供 ’ onRemove’ 信号,一旦荧光笔检测到先前匹配的规则不再匹配,就会发出该信号:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ## MainWindow.h private slots: void addMacro(const QSyntaxRule &rule, QString seq, QTextBlock block); void removeMacro(QCodeEditorBlockData *data); // Add this to the slots // ## MainWindow::MainWindow // Add another connection connect(m_Editor->highlighter(), SIGNAL(onRemove(QCodeEditorBlockData*)), this, SLOT(removeMacro(QCodeEditorBlockData*))); // ## MainWindow::removeMacro foreach (const QTextBlock &b, m_RuleMap.keys()) { if (b.userData()) { auto *d = static_cast<QCodeEditorBlockData *>(b.userData()); if (d->id == data->id) { // Data is the same; block must be the one from before! m_Editor->removeKeyword(m_MacroMap.value(b)); m_RuleMap.remove(b); m_MacroMap.remove(b); } } }

实现这样一个使用起来相对简单的信号是一项艰巨的任务。查看“兴趣点”一章了解更多信息。

五 编译说明

为了编译 QCodeEditor,您需要定义 ’ KGL_BUILD’ 以将符号导出到动态库。如果你想构建一个静态库,只需定义’ KGL_STATIC’。还要确保您使用的是 Qt5或更高版本。

六 可关注的点

最大的障碍之一是正确渲染行号。虽然将行列添加为子小部件非常容易,但确定滚动时所有可见的行号却并非如此。在阅读 Qt 文档很长一段时间后,我想我可以跳到迭代中的下一行,并在当前行不再可见时立即停止迭代。

另一个大障碍是在按下制表键时实现多个选定行的缩进。我通过使用真正令人惊叹的 ’ QTextCursor::movePosition’ 方法解决了这个问题,这使得实现这个功能(和后缩进)变得很容易。

QTextBlock
尽管 QTextBlock 具有惊人的功能和可能性,但它仍然有一个弱点:对我们来说,在文本小部件中跟踪 QTextBlock 几乎是不可能的。为了实现一个允许删除关键字的信号,我首先尝试复制有问题的 QTextBlock,然后使用重载的 ‘==’ 运算符检查是否相等。这不起作用,因为行号可能会改变并导致等式失败。追踪 QTextBlock 的唯一可能性是使用 ’ setUserData’ 函数为其分配 QTextBlockUserData。为了实现这一点,我继承了 QTextBlockUserData 并将 auuid和 the存储regex string在其中。uuid(+ 一些 do-while 循环)确保该块在整个应用程序中真正保持唯一。通过这些测量,‘onRemove’ 信号终于可靠且没有错误。


文章参考链接:https://www.codeproject.com/Articles/1139741/QCodeEditor-Widget-for-Qt

最后

以上就是高挑服饰最近收集整理的关于QCodeEditor - 基于Qt的代码编辑器的全部内容,更多相关QCodeEditor内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部