Pyside2-Linenumbers在人错误的时候改变了字体的家庭/尺寸

0

的问题

我看着这个代码编辑例从官方Qt5网站 https://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html. 它是用C++编写的但我实现它在Python使用Pyside2.

例代码的工作,但是,当我试图改变的字体的家庭和大小 QPlainTextEdit 事情开始变得混乱。 我试着调整一个很大的不同领域的使用 fontMetrics 确定的高度,等等。

这里是一个小例的重现的问题

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

最大的一个问题是,似乎是一个顶部保证金抵消在退出明文我无法动态得到的"行号"的部件。 并设定时的编辑字体的画家的数字都不会画出同样的尺寸!?

没有人知道如何调整符号相同水平的相应文本,也得到他们是相同的大小在一个动态的方式,意思是如果字体将是定于别的东西他们都应该自动调整。

pyside2 python-3.x
2021-11-20 05:34:22
1

最好的答案

1

问题来自事实上,你正在使用两个字体为不同的目的:将 部件 字体和 字体。

每个字体有不同的方面,及其对可能有所不同,如果你考虑的那些字体,因为基地图坐标。

因为你们的绘图用文字而使用的部件的字体作为参考,结果是,只有绘图问题:

  • 即使有相同点的大小、不同的字体是绘在不同的高度,尤其是如果对准文本矩形是不正确(还注意到,你用不一致的准, Qt.AlignRight | Qt.AlignHCenter 总是会考虑的权利准和默认顶级排列)
  • 你使用的 部件 的字体指标设定的文字的矩形的高度,这不同于该文件的指标,因此只限的高度图。

不像其他小部件,丰富的文本编辑器在脱有两个字体设置:

  • 部件 字体;
  • (默认) 文件 的字体,它可以复盖一个QTextOption在文件;

该文件将 总是 继承的部件字体(或应用的字体)的默认,并且这也会发生时设置的字体的小部件在运行时,甚至对申请(除非字体已经明确设置 的部件).

设置的字体编辑通常是现为简单的情况,但是你要记住,字体传播,这样的孩子部件将继承的字体。

另一方面,设置默认字体为本文件不会传播到儿童,但是,如上面所解释的,可以通过应用的字体,如果这就是改变在运行时间。

最简单的解决方案,在你的情况下,将要设置的字体编辑部件而不是文件。 这样你就可确保LineNumberArea(其编辑的儿童)还将继承相同的字体。 用这种方法,你甚至都不需要设置的字体的画家,因为它将始终使用的部件的字体。

如果你想使用一种不同的字体,仍然保持正确的对,你得考虑的基线位置的字体使用的文件,并使用的参考基线的部件字体。 为了做到这一点,你必须翻译这块位置的差别的 ascent() 两个字体指标。

2021-11-20 13:08:21

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................