Created
October 20, 2024 10:06
-
-
Save thinkphp/591194d5672bbc3d461c4c220b57acda to your computer and use it in GitHub Desktop.
notepad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
from PyQt5.QtWidgets import (QApplication, QMainWindow, QAction, QFileDialog, QTabWidget, | |
QPlainTextEdit, QWidget, QTextEdit) | |
from PyQt5.QtGui import QColor, QPainter, QTextFormat | |
from PyQt5.QtCore import Qt, QRect, QSize | |
class LineNumberArea(QWidget): | |
def __init__(self, editor): | |
super().__init__(editor) | |
self.editor = editor | |
def sizeHint(self): | |
return QSize(self.editor.lineNumberAreaWidth(), 0) | |
def paintEvent(self, event): | |
self.editor.lineNumberAreaPaintEvent(event) | |
class PlainTextEdit(QPlainTextEdit): | |
def __init__(self): | |
super().__init__() | |
self.lineNumberArea = LineNumberArea(self) | |
self.blockCountChanged.connect(self.updateLineNumberAreaWidth) | |
self.updateRequest.connect(self.updateLineNumberArea) | |
self.cursorPositionChanged.connect(self.highlightCurrentLine) | |
self.updateLineNumberAreaWidth(0) | |
def lineNumberAreaWidth(self): | |
digits = 1 | |
max_value = max(1, self.blockCount()) | |
while max_value >= 10: | |
max_value /= 10 | |
digits += 1 | |
space = 3 + self.fontMetrics().horizontalAdvance('9') * digits | |
return space | |
def updateLineNumberAreaWidth(self, _): | |
self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0) | |
def updateLineNumberArea(self, rect, dy): | |
if dy: | |
self.lineNumberArea.scroll(0, dy) | |
else: | |
self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height()) | |
if rect.contains(self.viewport().rect()): | |
self.updateLineNumberAreaWidth(0) | |
def resizeEvent(self, event): | |
super().resizeEvent(event) | |
cr = self.contentsRect() | |
self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height())) | |
def lineNumberAreaPaintEvent(self, event): | |
painter = QPainter(self.lineNumberArea) | |
painter.fillRect(event.rect(), Qt.lightGray) | |
block = self.firstVisibleBlock() | |
block_number = block.blockNumber() | |
top = self.blockBoundingGeometry(block).translated(self.contentOffset()).top() | |
bottom = top + self.blockBoundingRect(block).height() | |
while block.isValid() and top <= event.rect().bottom(): | |
if block.isVisible() and bottom >= event.rect().top(): | |
number = str(block_number + 1) | |
painter.setPen(Qt.black) | |
painter.drawText(0, int(top), self.lineNumberArea.width(), self.fontMetrics().height(), | |
Qt.AlignRight, number) | |
block = block.next() | |
top = bottom | |
bottom = top + self.blockBoundingRect(block).height() | |
block_number += 1 | |
def highlightCurrentLine(self): | |
extra_selections = [] | |
if not self.isReadOnly(): | |
selection = QTextEdit.ExtraSelection() | |
line_color = QColor(Qt.yellow).lighter(160) | |
selection.format.setBackground(line_color) | |
selection.format.setProperty(QTextFormat.FullWidthSelection, True) | |
selection.cursor = self.textCursor() | |
selection.cursor.clearSelection() | |
extra_selections.append(selection) | |
self.setExtraSelections(extra_selections) | |
class Notepad(QMainWindow): | |
def __init__(self): | |
super().__init__() | |
self.initUI() | |
def initUI(self): | |
self.setGeometry(100, 100, 800, 600) | |
self.setWindowTitle('Notepad') | |
# Create tab widget | |
self.tabs = QTabWidget() | |
self.setCentralWidget(self.tabs) | |
# Create first tab | |
self.newFile() | |
# Create menu bar | |
menubar = self.menuBar() | |
fileMenu = menubar.addMenu('File') | |
# New file action | |
newAction = QAction('New', self) | |
newAction.setShortcut('Ctrl+N') | |
newAction.triggered.connect(self.newFile) | |
fileMenu.addAction(newAction) | |
# Open file action | |
openAction = QAction('Open', self) | |
openAction.setShortcut('Ctrl+O') | |
openAction.triggered.connect(self.openFile) | |
fileMenu.addAction(openAction) | |
self.show() | |
def newFile(self): | |
textEdit = PlainTextEdit() | |
self.tabs.addTab(textEdit, f"Untitled {self.tabs.count() + 1}") | |
self.tabs.setCurrentWidget(textEdit) | |
def openFile(self): | |
filename, _ = QFileDialog.getOpenFileName(self, "Open File", "", "Text Files (*.txt);;All Files (*)") | |
if filename: | |
with open(filename, 'r') as file: | |
content = file.read() | |
textEdit = PlainTextEdit() | |
textEdit.setPlainText(content) | |
self.tabs.addTab(textEdit, filename.split('/')[-1]) | |
self.tabs.setCurrentWidget(textEdit) | |
if __name__ == '__main__': | |
app = QApplication(sys.argv) | |
ex = Notepad() | |
sys.exit(app.exec_()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment