1. 程式人生 > >Linux下Qt製作程式碼編輯器

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語言的知識