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
|
| 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控件要好很多!
