Skip to content

Instantly share code, notes, and snippets.

@thinkphp
Created October 20, 2024 10:06
Show Gist options
  • Save thinkphp/591194d5672bbc3d461c4c220b57acda to your computer and use it in GitHub Desktop.
Save thinkphp/591194d5672bbc3d461c4c220b57acda to your computer and use it in GitHub Desktop.
notepad
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