| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- from PySide2.QtGui import *
- from PySide2 import QtCore, QtGui, QtWidgets
- from PySide2.QtCore import Qt
- class Editor(QtWidgets.QPlainTextEdit):
- def __init__(self, parent=None):
- super().__init__(parent)
- self.lineNumberArea = LineNumberArea(self)
- self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
- self.updateRequest.connect(self.updateLineNumberArea)
- self.cursorPositionChanged.connect(self.highlightCurrentLine)
- self.updateLineNumberAreaWidth(0)
- self.setLineWrapMode(QtWidgets.QPlainTextEdit.LineWrapMode.NoWrap)
- self.setReadOnly(True)
-
- def goToLine(self, center_line):
- total_num_of_lines = self.document().lineCount()
- # 计算每行的高度
- line_height = self.fontMetrics().lineSpacing()
- # 获取文本控件可视窗口的高度
- viewport_height = self.viewport().height()
- # 每行所需滚动条的值
- scroll_per_line = (self.verticalScrollBar().pageStep() + self.verticalScrollBar().maximum())/total_num_of_lines
-
- scroll_value = (center_line - viewport_height/2/line_height) * scroll_per_line
-
- # 移动光标
- cursor = self.textCursor()
- cursor.movePosition(QtGui.QTextCursor.Start)
- for i in range(center_line - 1):
- cursor.movePosition(QtGui.QTextCursor.Down, QtGui.QTextCursor.MoveAnchor)
- self.setTextCursor(cursor)
- self.verticalScrollBar().setValue(0)
- self.verticalScrollBar().setValue(scroll_value)
-
- def lineNumberAreaWidth(self):
- digits = 1
- count = max(1, self.blockCount())
- while count >= 10:
- count /= 10
- digits += 1
- space = 3 + self.fontMetrics().horizontalAdvance('9') * digits
- return space
- def updateLineNumberAreaWidth(self, newBlockCount):
- 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(QtCore.QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()))
- def highlightCurrentLine(self):
- extraSelections = []
- selection = QtWidgets.QTextEdit.ExtraSelection()
- lineColor = QtGui.QColor(232,232,255)
- selection.format.setBackground(lineColor)
- selection.format.setProperty(QtGui.QTextFormat.FullWidthSelection, True)
- selection.cursor = self.textCursor()
- selection.cursor.clearSelection()
- extraSelections.append(selection)
- self.setExtraSelections(extraSelections)
- class LineNumberArea(QtWidgets.QWidget):
- def __init__(self, editor):
- super().__init__(editor)
- self.editor = editor
- def sizeHint(self):
- return QtCore.QSize(self.editor.lineNumberAreaWidth(), 0)
- def paintEvent(self, event):
- painter = QtGui.QPainter(self)
- painter.fillRect(event.rect(), QtCore.Qt.lightGray)
- block = self.editor.firstVisibleBlock()
- blockNumber = block.blockNumber()
- top = self.editor.blockBoundingGeometry(block).translated(self.editor.contentOffset()).top()
- bottom = top + self.editor.blockBoundingRect(block).height()
- height = self.editor.fontMetrics().height()
- while block.isValid() and top <= event.rect().bottom():
- if block.isVisible() and bottom >= event.rect().top():
- number = str(blockNumber + 1)
- painter.setPen(QtCore.Qt.black)
- painter.drawText(0, top, self.width(), height, QtCore.Qt.AlignRight, number)
- block = block.next()
- top = bottom
- bottom = top + self.editor.blockBoundingRect(block).height()
- blockNumber += 1
|