概述
一 基本介绍
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必须选中“ ”复选框)或以编程方式将其添加到形式:
using namespace kgl;
// ## MainWindow::MainWindow
QCodeEditor *editor = new QCodeEditor;
setCentralWidget(editor); // or: ui->someLayout->addWidget(editor);
通过使用QCodeEditorDesign该类可以更改编辑器的视觉外观。在下面的示例中,我们假设代码编辑器被多个小部件包围,因此为其添加了边框。我们还修改了外观以具有“深色”风格:
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 文件中提取它们。
以编程方式:
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 文件:
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 规则的指南。但首先,我们的编辑器需要一些自动完成关键字:
// ## MainWindow::MainWindow
QStringList keywords = { "printf", "scanf" };
editor->setKeywords(keywords);
如果希望添加图标以暗示关键字是函数/成员/宏/… QStandardItemModel,则需要创建自定义并将其传递给“ QCodeEditor::setKeywordModel(model)”。
三 创建 XML 规则文件
XML 规则文件包含由多个子元素组成的最顶层元素。每个子元素都必须包含正则表达式或关键字列表,所有其他属性都是可选的:
<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问题的:
// ## 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’ 信号,一旦荧光笔检测到先前匹配的规则不再匹配,就会发出该信号:
// ## 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 - 基于Qt的代码编辑器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复