PyQt6实战7--文本编辑器

一个简单的文本编辑器

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.headName
        return 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 = dir
        self._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)
                    return
            fileEditor = 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 _format

STYLES = {
    '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 rules
        rules += [(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 formatting
        for 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

公众号

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值