原来一直想写一个类似Notepad++的东西,做代码高亮,其实也没什么好做的,因为已经有了很好的Notepad++,我也不像重复发明轮子,但是最近做Firefox插件开发做的挺多的,用Netbeans用的也很多,但是Netbeans一直有点不爽就是编译等等不太方便,有时候还会有profile的错误,导致不能编译,还要删除profile才行,这确实让人很郁闷。而刚好最近玩一下Qt,所以就看一下能不能做一个,首先得弄一下编译器的代码高亮,所以看了一下Qt的例子,还是有一个很不错的类去做的,这个类就是QSyntaxHighlighter。
首先,还是上图,这个程序其实很简单,不难理解。这下面是实际效果图(代码高亮部分)。

首先,我们要写一个highlighter类,写类的时候我们先写个头文件叫highlighter.h,来定义我们的高亮的类的结构。
#define HIGHLIGHTER_H
#include
<QSyntaxHighlighter>#include
<QHash>#include <QTextCharFormat>
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE class Highlighter : public QSyntaxHighlighter
{
Q_OBJECT //构造函数
public:
Highlighter(QTextDocument *parent = 0); //这里一定要继承这个方法,否则不能编译通过
protected:
void highlightBlock(const QString &text); private:
//定义一个规则的结构体
struct HighlightingRule
{
QRegExp pattern;
QTextCharFormat format;
};
//放一个Vector,相当于List了
QVector<HighlightingRule> highlightingRules;
QRegExp commentStartExpression;
QRegExp commentEndExpression;
//Qt里面关键字高亮的东西
QTextCharFormat keywordFormat;
QTextCharFormat classFormat;
QTextCharFormat singleLineCommentFormat;
QTextCharFormat multiLineCommentFormat;
QTextCharFormat commentFormat;
QTextCharFormat functionFormat;
QTextCharFormat stringFormat;
};
我们写完了头文件之后我们就要逐渐实现我们结构里面的方法了,这里最重要的就是初始化方法和highlighterBlock方法了,我们可以编写代码如下。
Highlighter::Highlighter(QTextDocument
*parent) : QSyntaxHighlighter(parent){
HighlightingRule rule;
//设置关键字的颜色
keywordFormat.setForeground(Qt::darkBlue);
keywordFormat.setFontWeight(QFont::Bold);
//创建关键字的参数
QStringList keywordPatterns;
//插入关键字
keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b";
//遍历关键字然后添加到rule里面去
foreach (const QString &pattern, keywordPatterns)
{
rule.pattern = QRegExp(pattern);
rule.format = keywordFormat;
highlightingRules.append(rule);
}
//同样我们还可以设置字符串的高亮样式
stringFormat.setForeground(Qt::darkMagenta);
rule.pattern = QRegExp("\".*\"");
rule.format = stringFormat;
highlightingRules.append(rule);
//这里非常重要,是多行注释里面需要的
commentStartExpression = QRegExp("/\\*");
commentEndExpression = QRegExp("\\*/");
}
上面的代码我们就初始化了一个highlighter对象,用于高亮我们的代码模块,我们可以按照我们自己的意愿添加任何关键字,并且我们还可以设置很多高亮格式,只要通过正则表达式去匹配,就能够设置我们的高亮格式了,例如上面我设置了字符串的高亮样式(匹配".*"),然后将字符串设置为紫色高亮样式。
我们实现了高亮样式之后,还需要事件highlightBlock方法进行我们的高亮的查询和匹配,代码如下所示。
{
//遍历rule,并在文本中替换文本样式
foreach (const HighlightingRule &rule, highlightingRules)
{
QRegExp expression(rule.pattern);
int index = expression.indexIn(text);
//如果还有索引
while (index >= 0)
{
int length = expression.matchedLength();
//设置高亮格式
setFormat(index, length, rule.format);
index = expression.indexIn(text, index + length);
}
}
//上面的代码按道理这样就应该结束的
//但是多行的注释显示并没有实现,这里就需要下面的方法
//设置当前的Block状态
setCurrentBlockState(0);
int startIndex = 0;
//和前面的逻辑一样,但是是多行进行扫描设置
if (previousBlockState() != 1)
{
startIndex = commentStartExpression.indexIn(text);
}
while (startIndex >= 0)
{
int endIndex = commentEndExpression.indexIn(text, startIndex);
int commentLength;
if (endIndex == -1)
{
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
}
else
{
commentLength = endIndex - startIndex
+ commentEndExpression.matchedLength();
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex
}
}
通过上面的代码我们就完成了一个highlighter,不过highlighter还不够成熟,如果你需要设置更多的关键字,就要自己添加关键字,如果要设置数字颜色,单引号的引用的颜色,就可以自己添加相应的规则再添加到rules里面去了。
{
highlighter = new Highlighter(ui->textEdit->document());
//设置字体
QFont font;
font.setFamily("Arial");
font.setFixedPitch(true);
font.setPixelSize(12);
//设置textEdit控件的字体
ui->textEdit->setFont(font);
//设置文本,这里我传递空文本
ui->textEdit->setPlainText("");
}
在主窗体中我们可以重新创建一个SetColor方法即可,如何创建我就不累述了,这里我们在主窗体的构造函数中调用这个方法即可,其中我设置了一些字体,让开发窗体看上去更好看一点,如果你想要其他的字体,也可以更改QFont对象来更改为其他字体。
看来QT做开发还是很方便的啊。。