読み込んでいます...
2009年07月26日

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

首先,还是上图,这个程序其实很简单,不难理解。这下面是实际效果图(代码高亮部分)。

首先,我们要写一个highlighter类,写类的时候我们先写个头文件叫highlighter.h,来定义我们的高亮的类的结构。

#ifndef HIGHLIGHTER_H
#define HIGHLIGHTER_H

#include <QSyntaxHighlighter>

#include <QHash>
#include
<QTextCharFormat>

QT_BEGIN_NAMESPACE
class QTextDocument;
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方法了,我们可以编写代码如下。 

#include "highlighter.h"

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方法进行我们的高亮的查询和匹配,代码如下所示。

void Highlighter::highlightBlock(const QString &text)
{
    
//遍历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 = commentStartExpression.indexIn(text, startIndex + commentLength);
    }
}

通过上面的代码我们就完成了一个highlighter,不过highlighter还不够成熟,如果你需要设置更多的关键字,就要自己添加关键字,如果要设置数字颜色,单引号的引用的颜色,就可以自己添加相应的规则再添加到rules里面去了。 

void MainWindow::SetColor()
{
    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对象来更改为其他字体。

314路过 1评论 QT 阅读全文..
  1. m8fen @

    看来QT做开发还是很方便的啊。。

:-D :-? 8) :cry: 8-O :lol: :-x :-| :?: :-P :oops: :roll: :( :) :-o :wink: more »