PyQt5 打造編輯器


效果如下

  • 多標簽
  • 智能提示
  • 快捷鍵

思路

編輯器(右側部分)采用 monaco editor ,monaco editor是微軟開源的編輯器,使用TypeScript編寫,是大名鼎鼎的VSCode編輯器的內核。所以其使用習慣和VSCode完全相同。 monaco editor

monaco editor 是需要運行在瀏覽器中的(supports IE 11, Edge, Chrome, Firefox, Safari and Opera.), 那么怎么能將它嵌入Qt中呢? Qwebengineview 控件可以幫我們實現.

1. 定義編輯器類

Editor類繼承自QWebEngineView,所以才能使用load方法加載本地HTML文件

import os
from PyQt5 import QtWidgets
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView


class Editor(QWebEngineView):
    def __init__(self, par):
        super().__init__(par)
        self.editor_flag = []

        # 這里是本地html路徑,需根據實際情況進行修改.
        self.editor_index = (os.path.split(os.path.realpath(__file__))[0]) + "/../utils/index.html"
        self.load(QUrl.fromLocalFile(self.editor_index))

    def get_value(self, callback):
        """設置編輯器內容"""
        self.page().runJavaScript("monaco.editor.getModels()[0].getValue()", callback)

    def set_value(self, data):
        """獲取編輯器內容"""
        import base64
        data = base64.b64encode(data.encode())
        data = data.decode()
        self.page().runJavaScript("monaco.editor.getModels()[0].setValue(Base.decode('{}'))".format(data))

    def change_language(self, lan):
        """切換智能提示語言"""
        self.page().runJavaScript("monaco.editor.setModelLanguage(monaco.editor.getModels()[0],'{}')".format(lan))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Editor(None)
    w.setWindowTitle('Editor')
    w.show()
    sys.exit(app.exec_())

index.html 其實就是monaco editor 的入口,內容如下:

引入的monaco editor文件需要自行下載 下載地址

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <style type="text/css">
        html, body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<div id="container" style="width:100%;height:100%"></div>

<!-- 引入base64方法,設置編輯器內容時使用-->
<script src="./base64.js"></script>   
<!-- 根據實際路徑進行修改 -->
<script src="./package/dev/vs/loader.js"></script>
<script>
    // <!-- 根據實際路徑進行修改 -->
    require.config({paths: {'vs': './package/dev/vs'}});
    require(['vs/editor/editor.main'], function () {
        monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
        noSemanticValidation: true,
        noSyntaxValidation: true
    });
        editor = monaco.editor.create(document.getElementById('container'), {
            value: "",
            language: 'javascript',  //默認語言
            mouseWheelZoom:true,     // 鼠標滾輪縮放
            wordWrap:"on",           // 自動換行
            scrollBeyondLastLine:false,
            minimap:{
                enabled:false          // 顯示右側小地圖
            }
        });
        window.onresize = function () {
            editor.layout();
        };
    });
</script>
</body>
</html>

啟動后效果如下:

2. 在主界面中添加編輯器標簽(多標簽的實現)

  • 增加標簽
  • 關閉標簽

QTabwidget剛好可以滿足多標簽的需求,下面有幾個問題要解決:

  1. 每個標簽右上角顯示關閉按鈕
    默認情況下,標簽是不顯示關閉按鈕的,可以通過設置self.tabWidget.setTabsClosable(True)方法顯示出關閉按鈕.

  2. 關閉按鈕點擊事件

    self.tabWidget.tabCloseRequested.connect(self.closeTab)
    
    def closeTab(self):
    # 獲取當前處於激活狀態的標簽
    i = self.tabWidget.currentIndex()
    self.tabWidget.removeTab(i)
    
  3. 增加頁面

    new_tab = Editor(self)
    self.tabWidget.addTab(new_tab, tab_name)
    self.tabWidget.setCurrentWidget(new_tab)
    


免責聲明!

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



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