PYQT5:基于QsciScintilla的代码编辑器分析10--语法高亮颜色选择

这里提供本编辑器可执行文件(exe)的下载链接:
1.Code51.Code51_STC
2.百度盘链接::https://pan.baidu.com/s/1Ihxb7WX0ozUuRs3KFyzApQ
提取码:i6my
3.源代码:百度盘链接:https://pan.baidu.com/s/1jlRvWgN2LFHTtnKogeUZZw
提取码:w437
4.源代码的码云链接:https://gitee.com/huangweide001/code4STC51

读者在调试代码时,可以直接运行主文件《texteditor2.py》。
————————————————
版权声明:本文为CSDN博主「hwd00001」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hwd00001/article/details/103082826

这个编辑器在使用过程中,有时候觉得某些颜色不好,要更改,所以在编辑器中增加了语法高亮的颜色选择。位置在《菜单->设置->颜色设置》:
颜色设置

1.颜色设置对话框

1.1 使用Qt Designer生成界面代码

先在Qt Designer画好一个Dialog,(默认的全部是黑色字体,下图是在初始化时改变了字体颜色)
在这里插入图片描述
自动生成下面的代码:

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(312, 324)
        Dialog.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        Dialog.setAcceptDrops(False)
        Dialog.setSizeGripEnabled(True)
        Dialog.setModal(False)
        self.listStyles = QtWidgets.QListWidget(Dialog)
        self.listStyles.setGeometry(QtCore.QRect(10, 40, 181, 271))
        self.listStyles.setFrameShadow(QtWidgets.QFrame.Plain)
        self.listStyles.setObjectName("listStyles")
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        self.defaultButton = QtWidgets.QPushButton(Dialog)
        self.defaultButton.setGeometry(QtCore.QRect(220, 140, 75, 23))
        self.defaultButton.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.defaultButton.setObjectName("defaultButton")
        self.okButton = QtWidgets.QPushButton(Dialog)
        self.okButton.setGeometry(QtCore.QRect(220, 210, 75, 23))
        self.okButton.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.okButton.setObjectName("okButton")
        self.cancelButton = QtWidgets.QPushButton(Dialog)
        self.cancelButton.setGeometry(QtCore.QRect(220, 280, 75, 23))
        self.cancelButton.setObjectName("cancelButton")
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(10, 10, 171, 21))
        self.label.setObjectName("label")

        self.retranslateUi(Dialog)
        self.okButton.clicked.connect(Dialog.accept)    #Dialog.accept() 是内建函数,不用使用者实现
        self.cancelButton.clicked.connect(Dialog.reject) #Dialog.reject() 是内建函数,不用使用者实现
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "color Dialog"))
        __sortingEnabled = self.listStyles.isSortingEnabled()
        self.listStyles.setSortingEnabled(False)
        item = self.listStyles.item(0)
        item.setText(_translate("Dialog", "Default"))
        item = self.listStyles.item(1)
        item.setText(_translate("Dialog", "Keyword"))
        item = self.listStyles.item(2)
        item.setText(_translate("Dialog", "KeywordSet2"))
        item = self.listStyles.item(3)
        item.setText(_translate("Dialog", "CommentDoc"))
        item = self.listStyles.item(4)
        item.setText(_translate("Dialog", "Comment"))
        item = self.listStyles.item(5)
        item.setText(_translate("Dialog", "CommentLine"))
        item = self.listStyles.item(6)
        item.setText(_translate("Dialog", "Number"))
        item = self.listStyles.item(7)
        item.setText(_translate("Dialog", "DoubleQuotedString"))
        item = self.listStyles.item(8)
        item.setText(_translate("Dialog", "SingleQuotedString"))
        item = self.listStyles.item(9)
        item.setText(_translate("Dialog", "PreProcessor"))
        item = self.listStyles.item(10)
        item.setText(_translate("Dialog", "Operator"))
        item = self.listStyles.item(11)
        item.setText(_translate("Dialog", "UnclosedString"))
        item = self.listStyles.item(12)
        item.setText(_translate("Dialog", "Background"))
        item = self.listStyles.item(13)
        item.setText(_translate("Dialog", "CaretLine"))
        self.listStyles.setSortingEnabled(__sortingEnabled)
        self.defaultButton.setText(_translate("Dialog", "默认"))
        self.okButton.setText(_translate("Dialog", "OK"))
        self.cancelButton.setText(_translate("Dialog", "CANCEL"))
        self.label.setText(_translate("Dialog", "点击相应文字,即可修改颜色"))

1.2 响应对话框动作的代码

新建一个ColorDlg类,继承于上面的Ui_Dialog类,可以使界面和动作的改动互不影响。

class   ColorDlg(QDialog,Ui_Dialog):
    def __init__(self, parent=None):
        super(ColorDlg, self).__init__(parent)
        self.setupUi(self)
        if parent == None:
            return
        #1.主窗口作为父窗口 ,颜色的初始值由主窗口传入
        self.parent = parent  
        self.DlgRepaint()
    def DlgRepaint(self):
        #2.设置每个item的颜色
        for i in range(0, self.listStyles.count()):
            itm = self.listStyles.item(i)
            cl=QColor(self.parent.colorDict[itm.text()])
            #2.1 编辑区的背景 和 焦点行背景,设置底色
            if itm.text() == 'Background' or itm.text() == 'CaretLine':
                itm. setBackground(cl)
            #2.2 其它项设置字体颜色
            else:
                itm.setForeground(cl)            
        self.repaint()
    # QListWidget的单击信号的槽函数
    def on_listStyles_clicked(self):
        itm=self.listStyles.currentItem()
        cl=QColorDialog.getColor(QColor(self.parent.colorDict[itm.text()]))
        if cl.isValid():
            try:
                self.parent.colorDict[itm.text()] = cl.name()   #把有效的颜色保存到颜色字典中
            except:
                pass
            # 把刚刚点击的地方更新颜色
            if itm.text() == 'Background' or itm.text() == 'CaretLine':
                itm. setBackground(cl)
            else:
                itm.setForeground(cl)
    def on_defaultButton_clicked(self):
        global g_colorDict
        self.parent.colorDict=copy.deepcopy(g_colorDict)  
        self.DlgRepaint()

上面ColorDlg.on_listStyles_clicked(self)这个函数,无须显式使用self.listStyles.clicked.connect(self.on_listStyles_clicked),只要使用 on_控件名_clicked()的模式命名槽函数,编译器就自动把槽函数链接到信号上。
ColorDlg.on_defaultButton_clicked()这个是“默认”按钮的槽函数,将一个默认的颜色字典复制到主窗口的颜色字典,恢复出厂设置。
这个文件的完整代码放到最后,以免影响后面的内容。

2.主窗口调用颜色设置对话框

在MainWindow.init()中,在”菜单->设置“增加一个颜色设置的动作,以及从《setting.ini》读取已保存的颜色设置:

		......
		#初始化颜色字典
        self.colorDict=copy.deepcopy(g_colorDict)
    	......
        colorSettingAction = self.createAction("颜色设置", self.OpenColorSettingDlg, None, None, 
                                                            '设置关键字颜色', checkable=False)
        self.addActions(SettingMenu,(SettingAction, complierSettingAction,colorSettingAction ))
        ......        
        #读取 style 颜色        
        for style in self.colorDict.keys():
            str1 = 'color/' + style
            str1 = settings.value(str1)
            if str1 is not None:
                self.colorDict[style] = str1

调用颜色对话框的槽函数代码:

    def OpenColorSettingDlg(self):
        SettingDlg = ColorDlg(self)
        #2.打开对话框    
        ret = SettingDlg.exec_()
        if not ret :
            return
        #3.保存设置
        settings=QSettings("setting.ini",QSettings.IniFormat)
        for style in self.colorDict.keys():
            str1 = 'color/' + style
            settings.setValue(str1, self.colorDict[style])        
        #4.将打开的文件关闭再重新打开    
        self.repaintMDI()

3.语法高亮的颜色设置在LexerCPP中实现

在第5章 5–多文档编辑区介绍的《MyLexerCPP》代码中,关于颜色的设置是常数:

        self.setColor(QColor("#B0171F"), QsciLexerCPP.Keyword) 

变成这样即可:

        self.setColor(QColor(self.parent().win.colorDict['Keyword'                    ]), QsciLexerCPP.Keyword ) 

关于背景色,有一个地方要注意,如果仅仅这样设置:

        self.setPaper(QColor(self.parent().win.colorDict[ 'Background'  ]))    #设置底色

底色不能覆盖这个屏幕,效果是这样的:
在这里插入图片描述
还有加上下面的代码:

        for i in range(0, QsciScintillaBase.STYLE_MAX):
            desc = self.description(i)
            if desc: 
                self.setEolFill(True, i)    #将填充的底色延伸到屏幕的右端;否则默认只有文字的地方。

这样才可以达到理想的效果:
在这里插入图片描述

4.ColorDlg的完整代码

# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import copy
g_colorDict={'Default'                  :'#000000',
                        'Keyword'                  :'#B0171F'   ,        
                        'KeywordSet2'            :'#7f0000'   ,
                        'CommentDoc'              :'#008000'    , 
                        'Comment'                  :'#008000'    , 
                        'CommentLine'            :'#008000'    ,
                        'Number'                    :'#007f7f' ,
                        'DoubleQuotedString' :'#ff00ff'   ,
                        'SingleQuotedString' :'#ff00ff'  ,
                        'PreProcessor'           :'#be07ff'  ,   
                        'Operator'                 :'#191970',
                        'UnclosedString'       :'#0000FF', 
                        'Background'              :'#b2b2b2', 
                        'CaretLine'              :'#FFCFCF'  
                    }
class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(312, 324)
        Dialog.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        Dialog.setAcceptDrops(False)
        Dialog.setSizeGripEnabled(True)
        Dialog.setModal(False)
        self.listStyles = QtWidgets.QListWidget(Dialog)
        self.listStyles.setGeometry(QtCore.QRect(10, 40, 181, 271))
        self.listStyles.setFrameShadow(QtWidgets.QFrame.Plain)
        self.listStyles.setObjectName("listStyles")
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        item = QtWidgets.QListWidgetItem()
        self.listStyles.addItem(item)
        self.defaultButton = QtWidgets.QPushButton(Dialog)
        self.defaultButton.setGeometry(QtCore.QRect(220, 140, 75, 23))
        self.defaultButton.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.defaultButton.setObjectName("defaultButton")
        self.okButton = QtWidgets.QPushButton(Dialog)
        self.okButton.setGeometry(QtCore.QRect(220, 210, 75, 23))
        self.okButton.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.okButton.setObjectName("okButton")
        self.cancelButton = QtWidgets.QPushButton(Dialog)
        self.cancelButton.setGeometry(QtCore.QRect(220, 280, 75, 23))
        self.cancelButton.setObjectName("cancelButton")
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(10, 10, 171, 21))
        self.label.setObjectName("label")

        self.retranslateUi(Dialog)
        self.okButton.clicked.connect(Dialog.accept)    #Dialog.accept() 是内建函数,不用使用者实现
        self.cancelButton.clicked.connect(Dialog.reject)    #Dialog.reject() 是内建函数,不用使用者实现
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "color Dialog"))
        __sortingEnabled = self.listStyles.isSortingEnabled()
        self.listStyles.setSortingEnabled(False)
        item = self.listStyles.item(0)
        item.setText(_translate("Dialog", "Default"))
        item = self.listStyles.item(1)
        item.setText(_translate("Dialog", "Keyword"))
        item = self.listStyles.item(2)
        item.setText(_translate("Dialog", "KeywordSet2"))
        item = self.listStyles.item(3)
        item.setText(_translate("Dialog", "CommentDoc"))
        item = self.listStyles.item(4)
        item.setText(_translate("Dialog", "Comment"))
        item = self.listStyles.item(5)
        item.setText(_translate("Dialog", "CommentLine"))
        item = self.listStyles.item(6)
        item.setText(_translate("Dialog", "Number"))
        item = self.listStyles.item(7)
        item.setText(_translate("Dialog", "DoubleQuotedString"))
        item = self.listStyles.item(8)
        item.setText(_translate("Dialog", "SingleQuotedString"))
        item = self.listStyles.item(9)
        item.setText(_translate("Dialog", "PreProcessor"))
        item = self.listStyles.item(10)
        item.setText(_translate("Dialog", "Operator"))
        item = self.listStyles.item(11)
        item.setText(_translate("Dialog", "UnclosedString"))
        item = self.listStyles.item(12)
        item.setText(_translate("Dialog", "Background"))
        item = self.listStyles.item(13)
        item.setText(_translate("Dialog", "CaretLine"))
        self.listStyles.setSortingEnabled(__sortingEnabled)
        self.defaultButton.setText(_translate("Dialog", "默认"))
        self.okButton.setText(_translate("Dialog", "OK"))
        self.cancelButton.setText(_translate("Dialog", "CANCEL"))
        self.label.setText(_translate("Dialog", "点击相应文字,即可修改颜色"))

class   ColorDlg(QDialog,Ui_Dialog):
    def __init__(self, parent=None):
        super(ColorDlg, self).__init__(parent)
        self.setupUi(self)
        if parent == None:
            return
        #1.主窗口作为父窗口 ,颜色的初始值由主窗口传入
        self.parent = parent  
        self.DlgRepaint()
    def DlgRepaint(self):
        #2.设置每个item的颜色
        for i in range(0, self.listStyles.count()):
            itm = self.listStyles.item(i)
            cl=QColor(self.parent.colorDict[itm.text()])
            #2.1 编辑区的背景 和 焦点行背景,设置底色
            if itm.text() == 'Background' or itm.text() == 'CaretLine':
                itm. setBackground(cl)
            #2.2 其它项设置字体颜色
            else:
                itm.setForeground(cl)            
        self.repaint()
        #3. 点击查找按钮的信号的槽函数
    def on_listStyles_clicked(self):
        itm=self.listStyles.currentItem()
        cl=QColorDialog.getColor(QColor(self.parent.colorDict[itm.text()]))
        if cl.isValid():
            try:
                self.parent.colorDict[itm.text()] = cl.name()   #把有效的颜色保存到颜色字典中
            except:
                pass
            # 把刚刚点击的地方更新颜色
            if itm.text() == 'Background' or itm.text() == 'CaretLine':
                itm. setBackground(cl)
            else:
                itm.setForeground(cl)
            #self.repaint()
    def on_defaultButton_clicked(self):
        global g_colorDict
        self.parent.colorDict=copy.deepcopy(g_colorDict)  
        self.DlgRepaint()
'''            
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    #Dialog = QtWidgets.QDialog()
    ui = ColorDlg()
    #ui.setupUi(Dialog)
    ui.show()
    sys.exit(app.exec_())
'''

posted @ 2019-12-12 15:00  汉塘阿德  阅读(86)  评论(0编辑  收藏  举报  来源