这是我的文本编辑器的代码,
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 "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>
我试过使用QDraw仍然不知道该怎么做 我画了一个边距,左边应该有行号,写到这是写文字的地方。
现在我希望它在编辑器中写的文本行旁边显示行号,但到目前为止还没有成功!
请其他程序员帮我解决这个问题! !!提前致谢!!
答案 0 :(得分:3)
一个简单的解决方案是创建一个符合您要求的自定义窗口小部件,然后将其提升为在.ui中使用它,使用Code Editor Example创建自定义窗口小部件。
<强> 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
然后我们使用Qt Designer打开.ui
,右键单击QPlainTextEdit
并选择Promoted Widgets
,将出现一个对话框并填写图像显示的字段:
然后按Add
按钮,然后按Promote
按钮。
注意:没有必要使用Line,并删除插槽计算位置。
<强> 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())
输出:
您可以在以下link
中找到完整的示例