Linux下Qt製作程式碼編輯器
原始碼已上傳,有需要可以下載:
0.開發環境
看了那麼多部落格,沒幾個說明自己的開發環境的,所以開頭先說明一下這個程式碼編輯器的開發環境
系統 deepin15.5
核心
Qt版本 5.8.0
1.編輯器預覽
下面進入正文,先來看一下這個編輯器的基本情況
有基本的語法高亮\自動補全\換行縮排\括號匹配.
選單欄有基本功能的實現,能選擇不同的語言來進行語法高亮.
基本上實現了一個程式碼編輯器的基本功能.
接下來將從程式碼編輯器主體的實現和選單欄的實現開始說.
2.專案的建立
建立一個Qt Widgets Application.
設定預設.
3.QScintilla庫介紹
語法高亮\自動補全\換行縮排\括號匹配\行號顯示的功能主要由一個重要的外部庫實現--Scintilla
官網:https://www.scintilla.org
Qt下這個庫叫QScintilla
下載:https://riverbankcomputing.com/software/qscintilla/download
說明文件:http://pyqt.sourceforge.net/Docs/QScintilla2/index.html
功能的實現主要參照了兩人的部落格,在此非常感謝(ps:兩人的QScintilla都打錯了)
在此要修正一下兩個部落格說到的QScintilla的配置問題
在.pro檔案新增標頭檔案以及動態連結庫的引用:
INCLUDEPATH += Qt4Qt5資料夾的地址
Qt4Qt5資料夾在下載完解壓後的資料夾中
然後Qt中右鍵工程選擇新增外部庫
選擇編譯生成的.a檔案.
這樣pro檔案就添加了外部庫的內容.
4.實現 語法高亮\自動補全\換行縮排\括號匹配\行號顯示
程式碼實現編輯器主體的QWidget介面
//widget.h//widget.h class widget : public QWidgetclass widget : publ { Q_OBJECT public: widget(QWidget *parent = 0); //~widget(); QsciScintilla *geteditor(){ //返回QScintilla的物件指標 return editor; } void setLexer(const QString &);//設定不同語言的詞法分析器 private: QsciScintilla *editor=new QsciScintilla(this); }; #endif // WIDGET_H
原始檔實現widget類的建構函式和設定詞法分析器函式
建構函式先實現行號提示\介面顯示\字型和編碼方式編碼方式設定為UTF-8,不然中文會亂碼設定編碼格式還有其他更簡短的函式實現,具體檢視QScintilla庫的說明檔案.
//行號提示
editor->setMarginType(0,QsciScintilla::NumberMargin);//設定編號為0的頁邊顯示行號。
editor->setMarginLineNumbers(0,true);//對該頁邊啟用行號
editor->setMarginWidth(0,15);//設定頁邊寬度
//介面
QVBoxLayout *pLayout = new QVBoxLayout(this);
pLayout->addWidget(editor);
pLayout->setContentsMargins(0,0,0,0);
//設定顯示字型
editor->setFont(QFont("Courier 10 Pitch"));
//設定編碼方式
editor->SendScintilla(QsciScintilla::SCI_SETCODEPAGE,QsciScintilla::SC_CP_UTF8);//設定編碼為UTF-8
下面是widget函式內的setLexer函式的實現
設定詞法分析器函式
QsciLexer *textLexer;
textLexer = new QsciLexerCPP;
editor->setLexer(textLexer);//給QsciScintilla設定詞法分析器
先設定好詞法分析器再設定程式碼提示等功能
//程式碼提示
QsciAPIs *apis = new QsciAPIs(textLexer);
apis->prepare();
editor->setAutoCompletionSource(QsciScintilla::AcsAll); //設定源,自動補全所有地方出現的
editor->setAutoCompletionCaseSensitivity(true); //設定自動補全大小寫敏感
editor->setAutoCompletionThreshold(2); //設定每輸入2個字元就會出現自動補全的提示
//設定自動縮排
editor->setAutoIndent(true);
//顯示選中行號
editor->setCaretLineVisible(true);
editor->setCaretLineBackgroundColor(Qt::lightGray);
//Enables or disables, according to enable, this display of indentation guides.
editor->setIndentationGuides(true);
//顯示行號背景顏色
//editor->setMarginsBackgroundColor(Qt::gray);
//It is ignored if an indicator is being used. The default is blue.
editor->setUnmatchedBraceForegroundColor(Qt::blue);
//括號匹配
editor->setBraceMatching(QsciScintilla::SloppyBraceMatch);
至此程式碼編輯器的功能基本實現
5.MainWindow的基本設定
建構函式要加上widget物件和當前文字的檔名
private:
widget *WidGet=new widget(this);
QString currentName;//當前文字的檔名
對應的建構函式實現要加上
setWindowTitle(tr("Qt程式碼編輯器"));
this->resize(QSize(600,500)); //設定初始視窗大小
setCentralWidget(WidGet); //設主體為程式碼編輯器
其他基本為槽函式,下面會講到
6.檔案功能的實現 新建\開啟\儲存\另存為\關閉
這裡就用到了QMainWindow的功能函式.
具體功能的實現參照了下面的部落格
沒改動的地方就不貼出來了
#1 基本上textEdit.document()物件改為
WidGet->geteditor()
#2 開啟函式(非槽函式)實現
void MainWindow::loadFile(const QString &fileName)
{
QFile file(fileName);
WidGet->setLexer(fileName);
if(!file.open(QFile::ReadOnly|QFile::Text))
{
QMessageBox::critical(this,
"critical",
"cannot read file"
);
return;
}
else
{
QTextStream in(&file);
WidGet->geteditor()->setText(in.readAll());
setCurrentFile(fileName);
}
}
增加了根據檔名設定語法分析器
WidGet->setLexer(fileName);
*注意 這是widget類中的setLexer函式,修改上面widget類中的setLexer函式實現根據不同檔名的字尾來實現不同語言的詞法分析器.
修改textEdit.setPlainText(in.readAll())為
WidGet->geteditor()->setText(in.readAll());
#3 另存為函式
bool MainWindow::slotSaveAs()
{
QString slcStr;
QString fileName =QFileDialog::getSaveFileName(this,
QString::fromLocal8Bit("檔案另存為"),
"",
tr("Config Files(*);;text(*.txt);;C(*.cpp);;python(*.py);;Java(*.java);;HTML(*html)"),
&slcStr
);
if(slcStr.startsWith("text")&&!fileName.endsWith(".txt")){
fileName+=".txt";
}
if(slcStr.startsWith("C")&&!fileName.endsWith(".cpp")){
fileName+=".cpp";
}
if(slcStr.startsWith("python")&&!fileName.endsWith(".py")){
fileName+=".py";
}
if(slcStr.startsWith("Java")&&!fileName.endsWith(".java")){
fileName+=".py";
}
if(slcStr.startsWith("HTML")&&!fileName.endsWith(".html")){
fileName+=".py";
}
if(fileName.isNull())
return false;
else if(saveFile(fileName))
loadFile(fileName);
else return false;
}
第七行函式可以實現在儲存的時候選擇不同的檔案型別
選擇的型別字串儲存在第八行的slcStr中對
之後的程式碼根據slcStr而在儲存的檔案中新增字尾來更改檔案型別
7.選單欄增加對不同語言的選擇以實現對不同語言的語法高亮
做法和在選單欄增添開啟\儲存等功能的做法大同小異
語言選擇的槽函式(以c為例)
void wgsetLexercpp(){
WidGet->setLexer(".cpp");
}
這樣就可以實現語言的選擇
8.總結
主要需要熟悉QScintilla庫的使用
難度不大但不能只依賴庫函式
要結合自己本身c語言的知識