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_())
'''