python - How to Add line Number in this TextEditor
问题描述
This is my code for the text Editor,
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())
This is my EditorUI.ui file!
<?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 "Consolas";
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>
I have tried Using QDraw still got no idea what to do, i have drawn a margin where to the left there should be line numbers, and to the write this is place to Write the text.
Now i want it to show line numbers beside the lines of text i write in the editor, but so far no success!
Please fellow programmers help me with this problem! !!Thanks in advance!!
解决方案
一个简单的解决方案是创建一个满足您要求的自定义小部件,然后将其推广以在 .ui 中使用它,使用代码编辑器示例创建自定义小部件。
代码编辑器.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
,将出现一个对话框并填写如图所示的字段:
然后按下Add
按钮并在Promote
按钮之后。
注意:不需要使用Line,去掉slot计算位置。
主文件
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())
输出:
您可以在以下链接中找到完整的示例
推荐阅读
- android - 如何在 android Bitmap 中将图像转换为 1bpp 字节数组
- laravel - 如何从 Laravel 中的集合中获取特定数组
- python - 调用 Matlab 函数可以在部署的 PyQt 应用程序中工作吗?
- python - GPFlow 模型对测试集给出了错误的预测
- c# - EntityFrameworkCore 单个导航器,用于具有同级实体的不同表
- json - 在天气 API 上返回未定义的 JSON
- reactjs - 在响应中获取 twitter api 时出错但在邮递员中工作
- javascript - 创建用于测试的模拟 JWT 令牌
- javascript - nextjs 中的自定义语言环境位置
- python - 正则表达式匹配尊称,后跟全名