如何在此文本编辑器中添加行号

Nix*_*xel 1 python pyqt python-3.x pyqt5

这是我的文本编辑器代码,

import sys
from collections import Counter
from PyQt5.QtCore import pyqtRemoveInputHook
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction
from PyQt5 import uic
Ui_MainWindow, QtBaseClass = uic.loadUiType('EditorUI.ui')

class MyApp(QMainWindow):
    def __init__(self):
        self.newLines = 1
        super(MyApp, self).__init__(None)
        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')

        # New Action
        self.newAction = QAction('&New', self)
        self.newAction.triggered.connect(self.NewCall)
        fileMenu.addAction(self.newAction)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.textEdit.setViewportMargins(35, 0, 0, 0)
        self.ui.textEdit.textChanged.connect(self.NumNewLines)

    def NumNewLines(self): # Returns Number of lines Of text written in the editor
        self.newLines = Counter(self.ui.textEdit.toPlainText())['\n']+1

    def NewCall(self):
        print('new')

if __name__ == '__main__':
    pyqtRemoveInputHook()
    app = QApplication(sys.argv)
    window = MyApp()
    window.setWindowTitle('PyEditor')
    window.showMaximized()
    window.show()
    sys.exit(app.exec())
Run Code Online (Sandbox Code Playgroud)

这是我的 EditorUI.ui 文件!

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1364</width>
    <height>681</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPlainTextEdit" name="textEdit">
    <property name="geometry">
     <rect>
      <x>123</x>
      <y>0</y>
      <width>1241</width>
      <height>681</height>
     </rect>
    </property>
    <property name="styleSheet">
     <string notr="true">background-color: rgb(33, 33, 50);
font: 75 15pt &quot;Consolas&quot;;
color: rgb(255, 255, 255);</string>
    </property>
    <property name="plainText">
     <string/>
    </property>
   </widget>
   <widget class="Line" name="line">
    <property name="geometry">
     <rect>
      <x>150</x>
      <y>0</y>
      <width>20</width>
      <height>681</height>
     </rect>
    </property>
    <property name="orientation">
     <enum>Qt::Vertical</enum>
    </property>
   </widget>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>
Run Code Online (Sandbox Code Playgroud)

我尝试过使用 QDraw 仍然不知道该怎么做,我在左边应该有行号的地方画了一个边距,并且对于写入来说这是写入文本的地方。

现在我希望它在我在编辑器中编写的文本行旁边显示行号,但到目前为止没有成功!

请各位程序员帮我解决这个问题!!!提前致谢!!

eyl*_*esc 5

一个简单的解决方案是创建一个满足您要求的自定义小部件,然后将其提升为在 .ui 中使用它,使用代码编辑器示例创建自定义小部件。

\n\n

代码编辑器.py

\n\n
from PyQt5.QtWidgets import QWidget, QPlainTextEdit, QApplication, QTextEdit\nfrom PyQt5.QtGui import QColor, QTextFormat, QPainter\nfrom PyQt5.QtCore import QRect, pyqtSlot, Qt\n\n\nclass LineNumberArea(QWidget):\n    def __init__(self, editor):\n        QWidget.__init__(self, parent=editor)\n        self.codeEditor = editor\n\n    def sizeHint(self):\n        return QSize(self.codeEditor.lineNumberAreaWidth(), 0)\n\n    def paintEvent(self, event):\n        self.codeEditor.lineNumberAreaPaintEvent(event)\n\nclass CodeEditor(QPlainTextEdit):\n    def __init__(self, parent=None):\n        QPlainTextEdit.__init__(self, parent)\n        self.lineNumberArea = LineNumberArea(self)\n        self.blockCountChanged.connect(self.updateLineNumberAreaWidth)\n        self.updateRequest.connect(self.updateLineNumberArea)\n        self.cursorPositionChanged.connect(self.highlightCurrentLine)\n        self.updateLineNumberAreaWidth(0)\n        self.highlightCurrentLine()\n\n    def lineNumberAreaPaintEvent(self, event):\n        painter = QPainter(self.lineNumberArea)\n        painter.fillRect(event.rect(), Qt.lightGray)\n\n        block = self.firstVisibleBlock()\n        blockNumber = block.blockNumber();\n        top = self.blockBoundingGeometry(block).translated(self.contentOffset()).top()\n        bottom = top + self.blockBoundingRect(block).height()\n\n        while block.isValid() and top <= event.rect().bottom():\n            if block.isVisible() and bottom >= event.rect().top():\n                number = str(blockNumber + 1)\n                painter.setPen(Qt.black)\n                painter.drawText(0, top, self.lineNumberArea.width(), \n                    self.fontMetrics().height(),\n                    Qt.AlignRight, number)\n            block = block.next()\n            top = bottom\n            bottom = top + self.blockBoundingRect(block).height()\n            blockNumber += 1\n\n    def lineNumberAreaWidth(self):\n        digits = len(str(self.blockCount()))\n        space = 3 + self.fontMetrics().width(\'9\')*digits\n        return space\n\n    def resizeEvent(self, event):\n        QPlainTextEdit.resizeEvent(self, event)\n        cr = self.contentsRect()\n        self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()))\n\n    @pyqtSlot(int)\n    def updateLineNumberAreaWidth(self, newBlockCount):\n        self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0);\n\n    @pyqtSlot()\n    def highlightCurrentLine(self):\n        extraSelections = []\n        if not self.isReadOnly():\n            selection = QTextEdit.ExtraSelection()\n            lineColor = QColor(Qt.blue).lighter(160)\n            selection.format.setBackground(lineColor)\n            selection.format.setProperty(QTextFormat.FullWidthSelection, True)\n            selection.cursor = self.textCursor()\n            selection.cursor.clearSelection()\n            extraSelections.append(selection)\n        self.setExtraSelections(extraSelections)\n\n    @pyqtSlot(QRect, int)\n    def updateLineNumberArea(self, rect, dy):\n        if dy:\n            self.lineNumberArea.scroll(0, dy)\n        else:\n            self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height())\n        if rect.contains(self.viewport().rect()):\n            self.updateLineNumberAreaWidth(0)\n\n\nif __name__ == \'__main__\':\n    import sys\n\n    app = QApplication(sys.argv)\n    w = CodeEditor()\n    w.show()\n    sys.exit(app.exec_())\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在您必须推广该小部件,因此必须将这 3 个文件放在同一文件夹中:

\n\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 codeeditor.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 EditorUI.ui\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.py\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我们.ui用Qt Designer打开,右键单击QPlainTextEdit并选择Promoted Widgets,将出现一个对话框并填写字段,如图所示:

\n\n

在此输入图像描述

\n\n

然后按Add按钮,再按Promote按钮。

\n\n

注:不必使用Line,并去掉槽位计算位置。

\n\n

主要.py

\n\n
import sys\nfrom collections import Counter\nfrom PyQt5.QtCore import pyqtRemoveInputHook\nfrom PyQt5.QtWidgets import QMainWindow, QApplication, QAction\nfrom PyQt5 import uic\nUi_MainWindow, QtBaseClass = uic.loadUiType(\'EditorUI.ui\')\n\nclass MyApp(QMainWindow):\n    def __init__(self):\n        self.newLines = 1\n        super(MyApp, self).__init__(None)\n        menuBar = self.menuBar()\n        fileMenu = menuBar.addMenu(\'&File\')\n\n        # New Action\n        self.newAction = QAction(\'&New\', self)\n        self.newAction.triggered.connect(self.NewCall)\n        fileMenu.addAction(self.newAction)\n        self.ui = Ui_MainWindow()\n        self.ui.setupUi(self)\n\n    def NewCall(self):\n        print(\'new\')\n\nif __name__ == \'__main__\':\n    pyqtRemoveInputHook()\n    app = QApplication(sys.argv)\n    window = MyApp()\n    window.setWindowTitle(\'PyEditor\')\n    window.showMaximized()\n    window.show()\n    sys.exit(app.exec())\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出:

\n\n

在此输入图像描述

\n\n

您可以在以下链接中找到完整的示例

\n

  • 兄弟你是个巫师! (4认同)