Ho guardato questo editor di codice di esempio dal sito ufficiale Qt5 sito https://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html. È scritto in C++, ma l'ho implementato in Python utilizzando Pyside2.
Il codice di esempio funziona bene come è, tuttavia, quando provo a cambiare la famiglia di font e la dimensione del QPlainTextEdit
le cose iniziano a ottenere disordinato. Ho cercato di ottimizzare un sacco di diversi settori, come l'uso di fontMetrics
per determinare l'altezza.
Qui è un esempio minimale per riprodurre il problema
import sys
import signal
from PySide2.QtCore import Qt, QSize, QRect
from PySide2.QtGui import QPaintEvent, QPainter, QColor, QResizeEvent
from PySide2.QtWidgets import QWidget, QPlainTextEdit, QVBoxLayout
from PySide2 import QtCore
from PySide2.QtWidgets import QApplication
FONT_SIZE = 20
FONT_FAMILY = 'Source Code Pro'
class PlainTextEdit(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.init_settings_font()
def init_settings_font(self):
font = self.document().defaultFont()
font.setFamily(FONT_FAMILY)
font.setFixedPitch(True)
font.setPixelSize(FONT_SIZE)
self.document().setDefaultFont(font)
class LineNumberArea(QWidget):
TMP = dict()
def __init__(self, editor):
super().__init__(editor)
self._editor = editor
self._editor.blockCountChanged.connect(lambda new_count: self._update_margin())
self._editor.updateRequest.connect(lambda rect, dy: self._update_request(rect, dy))
self._update_margin()
def width(self) -> int:
# we use 1000 as a default size, so from 0-9999 this length will be applied
_max = max(1000, self._editor.blockCount())
digits = len(f'{_max}')
space = self._editor.fontMetrics().horizontalAdvance('0', -1) * (digits + 1) + 6
return QSize(space, 0).width()
def _update_line_geometry(self):
content_rect = self._editor.contentsRect()
self._update_geometry(content_rect)
def _update_geometry(self, content_rect: QRect):
self.setGeometry(
QRect(content_rect.left(), content_rect.top(), self.width(), content_rect.height())
)
def _update_margin(self):
self._editor.setViewportMargins(self.width(), 0, 0, 0)
def _update_request(self, rect: QRect, dy: int):
self._update(0, rect.y(), self.width(), rect.height(), self._editor.contentsRect())
if rect.contains(self._editor.viewport().rect()):
self._update_margin()
def _update(self, x: int, y: int, w: int, h: int, content_rect: QRect):
self.update(x, y, w, h)
self._update_geometry(content_rect)
# override
def resizeEvent(self, event: QResizeEvent) -> None:
self._update_line_geometry()
# override
def paintEvent(self, event: QPaintEvent):
painter = QPainter(self)
area_color = QColor('darkgrey')
# Clearing rect to update
painter.fillRect(event.rect(), area_color)
visible_block_num = self._editor.firstVisibleBlock().blockNumber()
block = self._editor.document().findBlockByNumber(visible_block_num)
top = self._editor.blockBoundingGeometry(block).translated(self._editor.contentOffset()).top()
bottom = top + self._editor.blockBoundingRect(block).height()
active_line_number = self._editor.textCursor().block().blockNumber() + 1
# font_size = storage.get_setting(Constants.Editor_font_size).value
font = self._editor.font()
while block.isValid() and top <= event.rect().bottom():
if block.isVisible() and bottom >= event.rect().top():
number_to_draw = visible_block_num + 1
if number_to_draw == active_line_number:
painter.setPen(QColor('black'))
else:
painter.setPen(QColor('white'))
font.setPixelSize(self._editor.document().defaultFont().pixelSize())
painter.setFont(font)
painter.drawText(
-5,
top,
self.width(),
self._editor.fontMetrics().height(),
int(Qt.AlignRight | Qt.AlignHCenter),
str(number_to_draw)
)
block = block.next()
top = bottom
bottom = top + self._editor.blockBoundingGeometry(block).height()
visible_block_num += 1
painter.end()
if __name__ == "__main__":
app = QApplication(sys.argv)
signal.signal(signal.SIGINT, signal.SIG_DFL)
window = QWidget()
layout = QVBoxLayout()
editor = PlainTextEdit()
line_num = LineNumberArea(editor)
layout.addWidget(editor)
window.setLayout(layout)
window.show()
sys.exit(app.exec_())
Uno dei principali problemi è che sembra che ci sia un margine superiore di offset in testo normale uscita che io sono in grado di ottenere dinamicamente il numero di widget. E quando si imposta l'editor di font e il pittore i numeri non verranno tracciate le stesse dimensioni?
Qualcuno sa come modificare i numeri di riga, per lo stesso livello orizzontale di testo corrispondenti e anche ottenere la stessa dimensione in modo dinamico, il che significa che se il font sarà qualcos'altro che dovrebbe essere regolati automaticamente.