Qt中文本編輯器實現語法高亮功能(Qscitinlla)


Scintilla是一個免費、跨平台、支持語法高亮的編輯控件。它完整支持源代碼的編輯和調試,包括語法高亮、錯誤指示、代碼完成(code completion)和調用提示(call tips)。能包含標記(marker)的頁邊(margin)可用於標記斷點、折疊和高亮當前行。而QScintilla是Scintilla在QT上的移植。使用該庫可以更為方便的開發Qt程序。

下面以windows開發為例:

Qscitinlla下載地址: https://riverbankcomputing.com/software/qscintilla/download

解壓,在Qt4Qt5目錄,用QtCreator打開qscintilla.pro,構建項目。

生成qscintilla2_qt5.lib或.a文件(本例子使用Qt5.7.1  MSVC2013)

 

1、創建QWidget工程

在.pro文件添加頭文件以及動態鏈接庫的引用:

INCLUDEPATH += C:/Users/pan/Desktop/QScintilla_gpl-2.10.1/Qt4Qt5
LIBS += -LC:/Users/pan/Desktop/QScintilla_gpl-2.10.1/build-qscintilla-Desktop_Qt_5_7_1_MSVC2013_64bit-Debug/debug/ -lqscintilla2_qt5d

或者不用添加INCLUDEPATH,直接將Qt4Qt5目錄中的Qsci目錄拷貝到工程中。

 

2、添加用到的頭文件

//QsciScintilla作為QWidget的控件,需要添加該控件的頭文件
#include <Qsci/qsciscintilla.h>
//以python語法作為例子,該語法分析器的頭文件
#include <Qsci/qscilexerpython.h>
//設置代碼提示功能,依靠QsciAPIs類實現
#include <Qsci/qsciapis.h>

  

3、設置具體功能代碼

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{

    QsciScintilla *editor=new QsciScintilla(this);
    //設置語法
    QsciLexerPython *textLexer = new QsciLexerPython;//創建一個詞法分析器
    editor->setLexer(textLexer);//給QsciScintilla設置詞法分析器

    //行號提示
    editor->setMarginType(0,QsciScintilla::NumberMargin);//設置編號為0的頁邊顯示行號。
    editor->setMarginLineNumbers(0,true);//對該頁邊啟用行號
    editor->setMarginWidth(0,15);//設置頁邊寬度
    //代碼提示
    QsciAPIs *apis = new QsciAPIs(textLexer);
    apis->add(QString("import"));
    apis->prepare();

    editor->setAutoCompletionSource(QsciScintilla::AcsAll);   //設置源,自動補全所有地方出現的
    editor->setAutoCompletionCaseSensitivity(true);   //設置自動補全大小寫敏感
    editor->setAutoCompletionThreshold(1);    //設置每輸入一個字符就會出現自動補全的提示

    pLayout = new QVBoxLayout(this);
    pLayout->addWidget(editor);
    pLayout->setContentsMargins(0,0,0,0);


}

  

說明:

行號顯示功能:

QsciScintilla左邊可顯示頁邊(Margins)和標記(Markers)。

頁邊是位於文本顯示區左邊的一豎條區域,它可以用於顯示行號、書簽、斷點標記等, Scintilla最多可以有5個頁邊(從左到右的編號為0~4)。

標記用來標記文本位置,如顯示自定義的內容,譬如斷點、錯誤位置等等,對於具有折疊功能的,可以使用32種標記(0-31),如果編輯器要支持代碼折疊功能,需要預留25-31,這7個作為專用折疊標記。

自動補全功能:

a 定義一個QsciAPIs類,構造函數中將父類指向你前面定義的lexer類。 
b 調用其中的類對應的add方法或者load方法想要補全的關鍵字。

對於補全的關鍵字比較少的可以通過add添加,如果補全內容比較多,可以通過load添加。

QsciAPIs*apis = new QsciAPIs(textLexer);  
if(!apis->load(QString("D://api.txt")))  
    QMessageBox::warning(this,QString("提示"),QString("讀取文件失敗"));  
else  
    apis->prepare();  

c 調用類對應的prepare方法來准備好關鍵字。 

d 在你前面定義的QsciScintilla類中的相關方法,常見的方法包括:

setAutoCompletionSource、setAutoCompletionCaseSensitivity、setAutoCompletionThreshold

其中,setAutoCompletionSource可設的屬性包括:

枚舉類型 描述
QsciScintilla::AcsNone 沒有自動補全的資源,即禁用自動補全提示功能
QsciScintilla::AcsAll 所有可用的資源都要自動補全提示,包括當前文檔中出現的名稱和使用QsciAPIs類加入的名稱
QsciScintilla::AcsDocument 當前文檔中出現的名稱都自動補全提示
QsciScintilla::AcsAPIs 使用QsciAPIs類加入的名稱都自動補全提示

 

 至此,可以完成一個簡單的python腳本編輯器。

 

 

4、編碼問題

Scintilla默認編碼是ANSI ,所以輸入中文字符會出現亂碼

 

可以給它設置為UTF-8,即添加代碼:(順便設置文本的字體)

//設置顯示字體
editor->setFont(QFont("Courier New"));
//設置編碼方式
editor->SendScintilla(QsciScintilla::SCI_SETCODEPAGE,QsciScintilla::SC_CP_UTF8);//設置編碼為UTF-8

 

5、高亮配色補充

然而,使用的過程中,對比一些其他的編輯器,發現存在問題:

該控件不支持python中的內置函數、以及一些編輯器通常把self也高亮實現。

可以看到源碼中支持的高亮類型:

// Returns the foreground colour of the text for a style.
QColor QsciLexerPython::defaultColor(int style) const
{
    switch (style)
    {
    case Default:
        return QColor(0x80,0x80,0x80);

    case Comment:
        return QColor(0x00,0x7f,0x00);

    case Number:
        return QColor(0x00,0x7f,0x7f);

    case DoubleQuotedString:
    case SingleQuotedString:
        return QColor(0x7f,0x00,0x7f);

    case Keyword:
        return QColor(0x00,0x00,0x7f);

    case TripleSingleQuotedString:
    case TripleDoubleQuotedString:
        return QColor(0x7f,0x00,0x00);

    case ClassName:
        return QColor(0x00,0x00,0xff);

    case FunctionMethodName:
        return QColor(0x00,0x7f,0x7f);

    case Operator:
    case Identifier:
        break;

    case CommentBlock:
        return QColor(0x7f,0x7f,0x7f);

    case UnclosedString:
        return QColor(0x00,0x00,0x00);

    case HighlightedIdentifier:
        return QColor(0x40,0x70,0x90);

    case Decorator:
        return QColor(0x80,0x50,0x00);
    }

    return QsciLexer::defaultColor(style);
}

其中的關鍵字定義:

// The list of Python keywords that can be used by other friendly lexers.
const char *QsciLexerPython::keywordClass =
    "and as assert break class continue def del elif else except exec "
    "finally for from global if import in is lambda None not or pass "
    "print raise return try while with yield";

  

 

 

Enumerator

Default 

The default.

Comment 

A comment.

Number 

A number.

DoubleQuotedString 

A double-quoted string.

SingleQuotedString 

A single-quoted string.

Keyword 

A keyword.

TripleSingleQuotedString 

A triple single-quoted string.

TripleDoubleQuotedString 

A triple double-quoted string.

ClassName 

The name of a class.

FunctionMethodName 

The name of a function or method.

Operator 

An operator.

Identifier 

An identifier.

CommentBlock 

A comment block.

UnclosedString 

The end of a line where a string is not closed.

HighlightedIdentifier 

A highlighted identifier. These are defined by keyword set

  1. Reimplement keywords() to define keyword set 2.
Decorator 

A decorator.

可以看到,該插件中應該是不支持python的內置函數的,這個內置函數和版本有關。

在自己的python中輸入dir(__builtins__),可將其重定向到文本中,記錄好這些需要高亮的語句。

#################################

對於print,由於在python2中,print "xxx"是作為關鍵字存在的,而使用print("xxx")的方式其為一個內置函數。

故,在python中輸入:

import keyword

print keywold.kwlist

  可以在輸出結果中看到print,而內置函數中也可以看到。

 

#################################

 參考上表中對於HighligetedIdentifier的介紹,可以知道,其對於自定義的值,kewords()函數傳遞的set值為2,重寫keywords()函數,定義類如下:

pythontest.h

class QsciLexerPythonTest : public QsciLexerPython
{
    //Q_OBJECT
public:
    const char *keywords(int set) const;
};

  

pythontest.cpp

const char * QsciLexerPythonTest::keywords(int set) const
{

    if(set == 2)
    {
        return "self str";
    }

    return QsciLexerPython::keywords(set);
}

  注意,繼承的類中不要有Q_OBJECT宏,否則會出現:error LNK2001: 無法解析的外部符號

 在Widget類中定義顏色:

textLexer->setColor(QColor(Qt::gray),QsciLexerPython::Comment);    //設置自帶的注釋行為灰色
textLexer->setColor(QColor(Qt::black),QsciLexerPython::FunctionMethodName);
textLexer->setColor(QColor(Qt::black),QsciLexerPython::ClassName);
textLexer->setColor(QColor(Qt::darkBlue),QsciLexerPython::Keyword);

textLexer->setColor(QColor(Qt::red),QsciLexerPython::HighlightedIdentifier);

  

這樣,對於self、str兩個自定義的關鍵字就可以用紅色高亮。

 

 

 

 

 

 

可以看到,使用這個庫開發是比較方便的,對比Qt自帶的QSyntaxHighlighter控件要好很多!

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM