一个简单的文本编辑器
features:
1.open 一个文件夹作为项目
2.save 保存当前窗口的内容
3.退出
4.双击文件可以打开文件内容
5.简单的python高亮
6.双击相同文件,会找到之前打开过的文件
打开一个文件夹
打开项目,双击打开文件
保存
代码:
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import *
from PyQt6.QtCore import *
from PyQt6.QtGui import *
import sys
import os
from highlight import *class FileSystemModel(QFileSystemModel):def __init__(self, headName, parent=None):super().__init__(parent)self.headName = headName'''只显示名称,不显示类型和其他的信息'''def columnCount(self, parent=QModelIndex()):return 1#修改表头的列名def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...):if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole:return self.headNamereturn super().headerData(section, orientation, role)class TextEditor(QMainWindow):def __init__(self):super().__init__()self._initUI()self._initConnect()def _initUI(self):self.setWindowTitle('Text Editor')self.resize(800, 600)centerWidget = QWidget()mainLayout = QHBoxLayout()self.left_file_tree = QTreeView()self.right_editor = QTabWidget()self.right_editor.setDocumentMode(True)self.right_editor.setTabsClosable(True)mainLayout.addWidget(self.left_file_tree)mainLayout.addWidget(self.right_editor)mainLayout.setSpacing(0)mainLayout.setContentsMargins(0, 0, 0, 0)mainLayout.setStretchFactor(self.left_file_tree, 1)mainLayout.setStretchFactor(self.right_editor, 4)centerWidget.setLayout(mainLayout)self.setCentralWidget(centerWidget)self._init_menu()def _init_menu(self):menubar = self.menuBar()menubar.setNativeMenuBar(False)fileMenu = menubar.addMenu('File')fileMenu.addAction('Open', self._open_folder)fileMenu.addAction('Save', self.save)fileMenu.addAction('Exit', self.close)def save(self):currentWidget = self.right_editor.currentWidget()if currentWidget:file_name = currentWidget.objectName()with open(file_name, 'w') as f:text = currentWidget.toPlainText()f.write(text)def _open_folder(self):dir = QFileDialog.getExistingDirectory(self, 'Open Folder', './')self.dir_path = dirself._init_file_tree(dir)self.right_editor.clear()def _init_file_tree(self, dir_path):dirname = os.path.basename(dir_path)self.model = FileSystemModel(dirname)self.model.setRootPath(dir_path)self.left_file_tree.setModel(self.model)#这里需要强制指定,否则显示root目录self.left_file_tree.setRootIndex(self.model.index(dir_path))def _initConnect(self):self.left_file_tree.doubleClicked.connect(self.on_file_tree_clicked)self.right_editor.tabCloseRequested.connect(self.close_current_tab)def close_current_tab(self, index):self.right_editor.removeTab(index)def on_file_tree_clicked(self, index):isDir = self.model.isDir(index)if not isDir:file_path = self.model.filePath(index)file_name = self.model.data(index)for i in range(self.right_editor.count()):tab = self.right_editor.widget(i)if tab.objectName() == file_path:self.right_editor.setCurrentIndex(i)returnfileEditor = QTextEdit()highlighter = SqlHighlighter(fileEditor.document())fileEditor.setObjectName(file_path)with open(file_path, 'r', encoding='utf-8') as f:fileEditor.setText(f.read())self.right_editor.addTab(fileEditor, file_name)self.right_editor.setCurrentIndex(self.right_editor.count()-1)def close(self):self.close()if __name__ == '__main__':app = QApplication(sys.argv)window = TextEditor()window.show()sys.exit(app.exec())
from PyQt6.QtWidgets import *
from PyQt6.QtGui import *
from PyQt6.QtCore import *def format(color, style=''):"""Return a QTextCharFormat with the given attributes."""_color = QColor()if type(color) is not str:_color.setRgb(color[0], color[1], color[2])else:_color.setNamedColor(color)_format = QTextCharFormat()_format.setForeground(_color)if 'bold' in style:_format.setFontWeight(QFont.Weight.Bold)if 'italic' in style:_format.setFontItalic(True)return _formatSTYLES = {'keyword': format([50, 50, 150], 'bold'),'operator': format([150, 150, 150]),'brace': format('darkGray'),'defclass': format([220, 220, 255], 'bold'),'string': format([20, 110, 100]),'string2': format([30, 120, 110]),'comment': format([128, 128, 128]),'self': format([150, 85, 140], 'italic'),'numbers': format([100, 150, 190]),
}class SqlHighlighter(QSyntaxHighlighter):keywords = ['def', 'return', 'for', 'in', 'while', 'if', 'elif', 'else','None', 'True', 'False', 'and', 'or', 'not', 'as', 'break','super', 'self', 'del', 'except', 'finally', 'is', 'class','lambda', 'try', 'with', 'from', 'nonlocal', 'pass', 'raise', 'assert', 'return', 'break', 'import', 'return', 'break', 'continue','yield', 'global',]braces = ['\{', '\}', '\(', '\)', '\[', '\]',]def __init__(self, document):super().__init__(document)rules = []# Keyword, operator, and brace rulesrules += [(r'\b%s\b' % w, 0, STYLES['keyword'])for w in SqlHighlighter.keywords]rules += [(r'%s' % b, 0, STYLES['brace'])for b in SqlHighlighter.braces]self.rules = [(QRegularExpression(pat), index, fmt) for (pat, index, fmt) in rules]def highlightBlock(self, text: str) -> None:"""Apply syntax highlighting to the given block of text."""# Do other syntax formattingfor expression, nth, format in self.rules:matchIterator = expression.globalMatch(text)while matchIterator.hasNext():# print(rule.pattern.pattern())match = matchIterator.next()self.setFormat(match.capturedStart(), match.capturedLength(), format)self.setCurrentBlockState(0)
代码地址:
GitHub - chunlaiqingke/Tiny-Tool
公众号