Как добавить номер строки в этом TextEditor - PullRequest
0 голосов
/ 28 апреля 2018

Это мой код для текстового редактора,

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())

Это мой файл 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>

Я пытался использовать QDraw, но понятия не имел, что делать, Я нарисовал поле, где слева должны быть номера строк, и для записи это место, чтобы написать текст.

Теперь я хочу, чтобы он показывал номера строк рядом со строками текста, которые я пишу в редакторе, но пока безуспешно!

Пожалуйста, коллеги-программисты, помогите мне с этой проблемой! !! Спасибо заранее !!

1 Ответ

0 голосов
/ 28 апреля 2018

Простое решение - создать пользовательский виджет, отвечающий вашим требованиям, а затем рекламировать его для использования в .ui; для создания пользовательского виджета используйте Пример редактора кода .

codeeditor.py

from PyQt5.QtWidgets import QWidget, QPlainTextEdit, QApplication, QTextEdit
from PyQt5.QtGui import QColor, QTextFormat, QPainter
from PyQt5.QtCore import QRect, pyqtSlot, Qt


class LineNumberArea(QWidget):
    def __init__(self, editor):
        QWidget.__init__(self, parent=editor)
        self.codeEditor = editor

    def sizeHint(self):
        return QSize(self.codeEditor.lineNumberAreaWidth(), 0)

    def paintEvent(self, event):
        self.codeEditor.lineNumberAreaPaintEvent(event)

class CodeEditor(QPlainTextEdit):
    def __init__(self, parent=None):
        QPlainTextEdit.__init__(self, parent)
        self.lineNumberArea = LineNumberArea(self)
        self.blockCountChanged.connect(self.updateLineNumberAreaWidth)
        self.updateRequest.connect(self.updateLineNumberArea)
        self.cursorPositionChanged.connect(self.highlightCurrentLine)
        self.updateLineNumberAreaWidth(0)
        self.highlightCurrentLine()

    def lineNumberAreaPaintEvent(self, event):
        painter = QPainter(self.lineNumberArea)
        painter.fillRect(event.rect(), Qt.lightGray)

        block = self.firstVisibleBlock()
        blockNumber = 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(blockNumber + 1)
                painter.setPen(Qt.black)
                painter.drawText(0, top, self.lineNumberArea.width(), 
                    self.fontMetrics().height(),
                    Qt.AlignRight, number)
            block = block.next()
            top = bottom
            bottom = top + self.blockBoundingRect(block).height()
            blockNumber += 1

    def lineNumberAreaWidth(self):
        digits = len(str(self.blockCount()))
        space = 3 + self.fontMetrics().width('9')*digits
        return space

    def resizeEvent(self, event):
        QPlainTextEdit.resizeEvent(self, event)
        cr = self.contentsRect()
        self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()))

    @pyqtSlot(int)
    def updateLineNumberAreaWidth(self, newBlockCount):
        self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0);

    @pyqtSlot()
    def highlightCurrentLine(self):
        extraSelections = []
        if not self.isReadOnly():
            selection = QTextEdit.ExtraSelection()
            lineColor = QColor(Qt.blue).lighter(160)
            selection.format.setBackground(lineColor)
            selection.format.setProperty(QTextFormat.FullWidthSelection, True)
            selection.cursor = self.textCursor()
            selection.cursor.clearSelection()
            extraSelections.append(selection)
        self.setExtraSelections(extraSelections)

    @pyqtSlot(QRect, int)
    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)


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    w = CodeEditor()
    w.show()
    sys.exit(app.exec_())

Теперь вы должны продвигать виджет, поэтому вы должны поместить 3 файла в одну папку:

.
├── codeeditor.py
├── EditorUI.ui
└── main.py

И затем мы открываем .ui с помощью Qt Designer, и правой кнопкой мыши нажимаем QPlainTextEdit и выбираем Promoted Widgets, появится диалоговое окно и заполните поля, как показано на рисунке:

enter image description here

Затем нажмите кнопку Add и после кнопки Promote.

Примечание: нет необходимости использовать линию и удалять позицию вычисления слота.

main.py

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)

    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())

Выход:

enter image description here

Полный пример вы можете найти в следующей ссылке

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...