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