lineNumberWidget.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. from PySide2.QtGui import *
  2. from PySide2.QtWidgets import QTextBrowser,QTextEdit
  3. from PySide2.QtCore import Qt
  4. class LineNumberWidget(QTextBrowser):
  5. def __init__(self, widget):
  6. super().__init__()
  7. self.__initUi(widget)
  8. def __initUi(self, widget):
  9. self.__lineCount = widget.document().lineCount()
  10. self.__size = int(widget.font().pointSizeF())
  11. self.__styleInit()
  12. # 尝试解决行号换行问题
  13. self.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
  14. self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  15. self.setTextInteractionFlags(Qt.NoTextInteraction)
  16. self.verticalScrollBar().setEnabled(False)
  17. widget.verticalScrollBar().valueChanged.connect(self.__changeLineWidgetScrollAsTargetedWidgetScrollChanged)
  18. self.__initLineCount()
  19. self.befor_hightlight_line = None
  20. def __changeLineWidgetScrollAsTargetedWidgetScrollChanged(self, v):
  21. self.verticalScrollBar().setValue(v)
  22. self.setWidthByStr()
  23. def __initLineCount(self):
  24. for n in range(1, self.__lineCount+1):
  25. self.append(str(n))
  26. def changeLineCount(self, n):
  27. max_one = max(self.__lineCount, n)
  28. diff = n-self.__lineCount
  29. if max_one == self.__lineCount:
  30. first_v = self.verticalScrollBar().value()
  31. for i in range(self.__lineCount, self.__lineCount + diff, -1):
  32. self.moveCursor(QTextCursor.End, QTextCursor.MoveAnchor)
  33. self.moveCursor(QTextCursor.StartOfLine, QTextCursor.MoveAnchor)
  34. self.moveCursor(QTextCursor.End, QTextCursor.KeepAnchor)
  35. self.textCursor().removeSelectedText()
  36. self.textCursor().deletePreviousChar()
  37. last_v = self.verticalScrollBar().value()
  38. if abs(first_v-last_v) != 2:
  39. self.verticalScrollBar().setValue(first_v)
  40. else:
  41. for i in range(self.__lineCount, self.__lineCount + diff, 1):
  42. self.append(str(i + 1))
  43. self.__lineCount = n
  44. def selectLine(self, line):
  45. position = self.document().findBlockByLineNumber(line-1).position()
  46. tc = self.textCursor()
  47. tc.setPosition(position, QTextCursor.MoveAnchor) # 直接跳转到start_pos
  48. tc.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
  49. return tc
  50. def highlightLineNumber(self, line):
  51. if self.befor_hightlight_line:
  52. self.clearHighlightLineNumber(self.befor_hightlight_line)
  53. fmt = QTextCharFormat()
  54. fmt.setFontWeight(QFont.Bold)
  55. fmt.setForeground(QBrush(QColor(0,0,0)))
  56. tc = self.selectLine(line)
  57. tc.mergeCharFormat(fmt) # 格式化选中文本
  58. tc.clearSelection() # 取消选中
  59. self.befor_hightlight_line = line
  60. def clearHighlightLineNumber(self, line):
  61. tc = self.selectLine(line)
  62. tc.setCharFormat(QTextCharFormat())
  63. def setValue(self, v):
  64. self.verticalScrollBar().setValue(v)
  65. def setFontSize(self, s: float):
  66. self.__size = int(s)
  67. self.__styleInit()
  68. def setWidthByStr(self):
  69. withd = (len(str(self.__lineCount)) + 2) * self.__size*0.7
  70. self.setFixedWidth(withd)
  71. def line_count(self):
  72. return self.__lineCount
  73. def __styleInit(self):
  74. self.__style = f'''
  75. QTextBrowser
  76. {{
  77. background: transparent;
  78. border: none;
  79. color: #AAA;
  80. font: {self.__size}pt;
  81. }}
  82. '''
  83. self.setStyleSheet(self.__style)
  84. self.setWidthByStr()