基于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_())