from PySide2.QtGui import * from PySide2.QtWidgets import QTextBrowser from PySide2.QtCore import Qt class LineNumberWidget(QTextBrowser): def __init__(self, widget): super().__init__() self.__initUi(widget) def __initUi(self, widget): self.__lineCount = widget.document().lineCount() self.__size = int(widget.font().pointSizeF()) self.__styleInit() self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setTextInteractionFlags(Qt.NoTextInteraction) self.verticalScrollBar().setEnabled(False) widget.verticalScrollBar().valueChanged.connect(self.__changeLineWidgetScrollAsTargetedWidgetScrollChanged) self.__initLineCount() self.befor_hightlight_line = None def __changeLineWidgetScrollAsTargetedWidgetScrollChanged(self, v): self.verticalScrollBar().setValue(v) self.setWidthByStr() def __initLineCount(self): for n in range(1, self.__lineCount+1): self.append(str(n)) def changeLineCount(self, n): max_one = max(self.__lineCount, n) diff = n-self.__lineCount if max_one == self.__lineCount: first_v = self.verticalScrollBar().value() for i in range(self.__lineCount, self.__lineCount + diff, -1): self.moveCursor(QTextCursor.End, QTextCursor.MoveAnchor) self.moveCursor(QTextCursor.StartOfLine, QTextCursor.MoveAnchor) self.moveCursor(QTextCursor.End, QTextCursor.KeepAnchor) self.textCursor().removeSelectedText() self.textCursor().deletePreviousChar() last_v = self.verticalScrollBar().value() if abs(first_v-last_v) != 2: self.verticalScrollBar().setValue(first_v) else: for i in range(self.__lineCount, self.__lineCount + diff, 1): self.append(str(i + 1)) self.__lineCount = n def selectLine(self, line): position = self.document().findBlockByLineNumber(line-1).position() tc = self.textCursor() tc.setPosition(position, QTextCursor.MoveAnchor) # 直接跳转到start_pos tc.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) return tc def highlightLineNumber(self, line): if self.befor_hightlight_line: self.clearHighlightLineNumber(self.befor_hightlight_line) fmt = QTextCharFormat() fmt.setFontWeight(QFont.Bold) fmt.setForeground(QBrush(QColor(0,0,0))) tc = self.selectLine(line) tc.mergeCharFormat(fmt) # 格式化选中文本 tc.clearSelection() # 取消选中 self.befor_hightlight_line = line def clearHighlightLineNumber(self, line): tc = self.selectLine(line) tc.setCharFormat(QTextCharFormat()) def setValue(self, v): self.verticalScrollBar().setValue(v) def setFontSize(self, s: float): self.__size = int(s) self.__styleInit() def setWidthByStr(self): withd = (len(str(self.__lineCount)) + 2) * self.__size*0.7 self.setFixedWidth(withd) def line_count(self): return self.__lineCount def __styleInit(self): self.__style = f''' QTextBrowser {{ background: transparent; border: none; color: #AAA; font: {self.__size}pt; }} ''' self.setStyleSheet(self.__style) self.setWidthByStr()