当前位置: 首页 > news >正文

基于python实现基础的文本编辑器

基于python与pyqt实现的一个简单的文本编辑器。

主要功能为文件的操作:打开文件,新建文件,保存与退出,

编辑功能主要为:粘贴,剪切,复制,以及查找功能

关于字数统计,因为字符原因是不够准确的,正常情况下背景为白色,但是黑色更护眼,可以基于代码进行相应的一个调整。

import sys
import re
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, qApp, QStatusBar, QMenuBar, QTextEdit, QDialog, \
    QVBoxLayout, QLineEdit, QPushButton, QListWidget, QMessageBox, QLabel, QFileDialog
from PyQt5.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor, QFont, QTextCursor, \
    QTextDocument  # 添加QTextDocument到导入列表
from PyQt5.QtCore import QRegularExpression


class MyWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("一个黑客创业者:文本编辑器")

        # 设置主部件
        self.textEdit = QTextEdit()
        self.setCentralWidget(self.textEdit)

        # 样式设置
        self.textEdit.setStyleSheet("""
            background-color: #2d2d2d;
            color: #ffffff;
            font-size: 14px;
            font-family: "Consolas";
        """)
        self.syntaxHighlighter = SyntaxHighlighter(self.textEdit.document())

        # 状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage('状态栏')
        self.statusBar.setStyleSheet("""
            background-color: #3f3f3f;
            color: #ffffff;
            font-size: 12px;
        """)

        # 菜单栏
        menu_bar = QMenuBar()
        self.setMenuBar(menu_bar)
        menu_bar.setStyleSheet("""
            background-color: #3f3f3f;
            color: #ffffff;
            font-size: 14px;
        """)

        # 文件菜单
        file_menu = menu_bar.addMenu("文件")
        self.create_file = file_menu.addAction("新建")
        self.create_file.setShortcut('Ctrl+N')
        self.create_file.triggered.connect(self.newFile)

        self.open = file_menu.addAction("打开")
        self.open.setShortcut("Ctrl+O")
        self.open.triggered.connect(self.openFile)

        self.save = file_menu.addAction("保存")
        self.save.setShortcut("Ctrl+S")
        self.save.triggered.connect(self.saveFile)

        self.exit = file_menu.addAction("退出")
        self.exit.setShortcut("Ctrl+E")
        self.exit.triggered.connect(qApp.quit)

        # 编辑菜单
        edit_menu = menu_bar.addMenu("编辑")
        edit_menu.addAction("复制").triggered.connect(self.textEdit.copy)
        edit_menu.addAction("粘贴").triggered.connect(self.textEdit.paste)
        edit_menu.addAction("剪切").triggered.connect(self.textEdit.cut)

        # 查找菜单
        search_menu = menu_bar.addMenu("查找")
        self.find_action = search_menu.addAction("查找")
        self.find_action.setShortcut("Ctrl+F")
        self.find_action.triggered.connect(self.showFindDialog)

        # 字数统计标签
        self.word_count_label = QLabel(self)
        self.statusBar.addPermanentWidget(self.word_count_label)
        self.update_word_count()

        self.textEdit.textChanged.connect(self.update_word_count)

    def newFile(self):
        self.textEdit.clear()
        self.statusBar.showMessage('新文件')

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(self, '打开文件', '', '文本文件 (*.txt);;所有文件 (*)')
        if fileName:
            with open(fileName, 'r', encoding='utf-8') as file:
                self.textEdit.setText(file.read())
        self.statusBar.showMessage('打开新文件')

    def saveFile(self):
        fileName, _ = QFileDialog.getSaveFileName(self, '保存文件', '', '文本文件 (*.txt);;所有文件 (*)')
        if fileName:
            with open(fileName, 'w', encoding='utf-8') as file:
                file.write(self.textEdit.toPlainText())

    def showFindDialog(self):
        find_dialog = QDialog(self)
        find_dialog.setWindowTitle("查找")
        layout = QVBoxLayout(find_dialog)

        self.search_edit = QLineEdit(find_dialog)
        self.search_button = QPushButton("查找", find_dialog)
        self.results_list = QListWidget(find_dialog)

        layout.addWidget(self.search_edit)
        layout.addWidget(self.search_button)
        layout.addWidget(self.results_list)

        self.search_button.clicked.connect(self.performSearch)

        find_dialog.exec_()

    def performSearch(self):
        query = self.search_edit.text()
        if not query:
            QMessageBox.warning(self, "警告", "请输入要查找的内容")
            return

        document = self.textEdit.document()
        cursor = QTextCursor(document)
        found_occurrences = False

        while True:
            cursor = document.find(query, cursor,
                                   QTextDocument.FindCaseSensitively | QTextDocument.FindWholeWords)
            if cursor.isNull():
                break
            found_occurrences = True
            selection_start = cursor.selectionStart()
            selection_end = cursor.selectionEnd()
            self.highlightFoundText(selection_start, selection_end)

        if not found_occurrences:
            QMessageBox.information(self, "信息", f"未找到 '{query}'")

    def highlightFoundText(self, start_pos, end_pos):
        extra_selections = []
        selection_format = QTextCharFormat()
        selection_format.setBackground(QColor("yellow"))

        selection = QTextEdit.ExtraSelection()
        selection.format = selection_format
        selection.cursor.setPosition(start_pos, QTextCursor.MoveAnchor)
        selection.cursor.setPosition(end_pos, QTextCursor.KeepAnchor)
        extra_selections.append(selection)

        self.textEdit.setExtraSelections(extra_selections)

    def update_word_count(self):
        text = self.textEdit.toPlainText()
        words = len(re.findall(r'\b\w+\b', text))
        self.word_count_label.setText(f'字数: {words}')


class SyntaxHighlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super().__init__(parent)

        keywordFormat = QTextCharFormat()
        keywordFormat.setForeground(QColor("blue"))
        keywordFormat.setFontWeight(QFont.Bold)

        commentFormat = QTextCharFormat()
        commentFormat.setForeground(QColor("green"))
        commentFormat.setFontItalic(True)

        stringFormat = QTextCharFormat()
        stringFormat.setForeground(QColor("red"))
        stringFormat.setFontWeight(QFont.Bold)

        keywords = ["def", "class", "import", "from", "if", "else", "elif", "for", "while", "return", "try", "except"]

        self.highlightingRules = []

        for word in keywords:
            escaped_word = re.escape(word)
            rule = QRegularExpression(rf"\b{escaped_word}\b")
            self.highlightingRules.append((rule, keywordFormat))

        rule = QRegularExpression(r"#[^\n]*")
        self.highlightingRules.append((rule, commentFormat))

        rule = QRegularExpression(r'"([^"\\]|\\.)*"')
        self.highlightingRules.append((rule, stringFormat))

    def highlightBlock(self, text):
        for pattern, format in self.highlightingRules:
            matchIterator = pattern.globalMatch(text)
            while matchIterator.hasNext():
                match = matchIterator.next()
                self.setFormat(match.capturedStart(), match.capturedLength(), format)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    # 应用全局样式表
    app.setStyleSheet("""
        QMainWindow {
            background-color: #2d2d2d;
        }
        QMenuBar {
            background-color: #3f3f3f;
            color: #ffffff;
            font-size: 14px;
        }
        QStatusBar {
            background-color: #3f3f3f;
            color: #ffffff;
            font-size: 12px;
        }
        QTextEdit {
            background-color: #2d2d2d;
            color: #ffffff;
            font-size: 14px;
            font-family: "Consolas";
        }
        QPushButton {
            background-color: #3f3f3f;
            color: #ffffff;
            border: 1px solid #2d2d2d;
            padding: 5px;
            font-size: 12px;
        }
        QLineEdit {
            background-color: #2d2d2d;
            color: #ffffff;
            border: 1px solid #2d2d2d;
            padding: 3px;
            font-size: 12px;
        }
        QListWidget {
            background-color: #2d2d2d;
            color: #ffffff;
            font-size: 12px;
        }
    """)

    w = MyWindow()
    w.resize(600, 400)
    w.show()
    sys.exit(app.exec_())

相关文章:

  • 5分钟快速搭建一个 SpringBoot3 + MyBatis-Plus 工程项目
  • 【Python项目】基于Python的答题卡识别与判分系统
  • 告别GitHub连不上!一分钟快速访问方案
  • 关于养成数值的感悟
  • Ubuntu20.04双系统安装及软件安装(五):VSCode
  • GIT 常用命令
  • 【数据挖掘】NumPy的索引与切片(Indexing Slicing)
  • 开源嵌入式实时操作系统NuttX介绍
  • 分布式环境下如何防止重复提交?AOP+Redis设计高可用的防重提交组件
  • 【基础3】快速排序
  • 嵌入式科普(34)通过对比看透DMA的本质
  • 第四十一:Axios 模型的 get ,post请求
  • C++----异常
  • Python数据可视化
  • PX4中的uavcan进程
  • python全栈-Linux基础
  • 策略模式处理
  • AI工具:deepseek+阶跃视频,生成好玩的视频
  • 教育强国建设“三年行动计划“分析
  • 如何快速上手RabbitMQ 笔记250304
  • 广州电子商务网站建设 v/企业文化内容范本
  • 小型网站建设公司价格低/软文推广文案范文
  • 摄影网站建设解决方案/网站优化策划书
  • 婚恋网站的渠道网络建设/南宁seo手段
  • 荆门做微信公众号的网站/未来网络营销的发展趋势
  • 厦门专业网站设计/免费源码下载网站