Pyside2-Linenumbers ใน codeeditor ไม่ถูกต้องตอนที่เปลี่ยนแบบอักษรครอบครัว/ขนาด

0

คำถาม

ฉันมองมาที่นี่รหัสเครื่องมือแก้ไขตัวอย่างจากทางการ Qt5 เว็บไซต์ https://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html. มันถูกเขียนใน C++แต่ฉันติดตั้งเพื่อใช้งานมันเป็นภาษาไพธอนใช้ Pyside2.

คนตัวอย่างเช่นรหัสได้ผลดีอย่างที่เป็นอย่างไรก็ตามตอนที่ฉันพยายามจะเปลี่ยนการแสดงแบบอักษรเป็นครอบครัวและขนาด QPlainTextEdit อย่างเริ่มจะยุ่งยาก ฉันพยายามจะ tweak องรอยที่แตกต่างกันมากมาช่องข้อมูลเหมือนการใช้ fontMetrics เพื่อกำหนดงานอดิเรกต้องสูงเป็นต้น

นี่คือขนาดเล็กที่สุดตัวอย่างที่ต้อง reproduce ปัญหา

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

หนึ่งของที่ใหญ่ที่สุดเรื่องนั้นมันดูเหมือนว่าจะมีขอบบนช่วงเวลาใน plaintext ทางออกซึ่งฉันไม่สามารถ dynamically เข้าไปในร linenumber วิดเจ็ต. และเมื่อการตั้งค่าเครื่องมือแก้ไขแบบอักษรที่แพนเทอร์เลขหมายจะไม่ถูกดึงไปในรูขนาดเดียวกัน!?

มีใครรู้วิธีที่จะปรับค่าหมายเลขบรรทัดเดียวกันกับที่ทางแนวนอนระดับเป็นที่สัมพันธ์กับข้อความแล้วก็พาพวกเขาต้องเป็นคนเดียวกันขนาดเป็นคลื่นทางนหมายถึงถ้าแบบอักษรที่จะถูกตั้งค่าเป็นอย่างอื่นอีกพวกมันทั้งหมดควรจะต้องปรับตัวโดยอัตโนมัติ

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

คำตอบที่ดีที่สุด

1

ปัญหาของออกมาจากความจริงที่ว่าคุณกำลังใช้สองแบบอักษรสำหรับแตกต่างประสงค์ที่ วิดเจ็ต แบบอักษรและ เอกสาร แบบอักษรได้

แต่ละแบบอักษรมีต่างๆและตำแหน่งของมันอาจจะแตกต่างกันถ้าคุณคิดว่าพวกนั้นแบบอักษรเป็นฐานสำหรับการวาดพิกัด

ตั้งแต่คุณกำลังวาดภาพกับเอกสารแบบอักษรแต่โดยใช้วิดเจ็ตแบบอักษรเป็นตัวผลคือที่คุณจะต้องเขียนเรื่อง:

  • แม้แต่กับเดียวกันประเด็นขนาดแตกต่างแบบอักษรคือดึงดูดที่แตกต่างไฮโดยเฉพาะอย่างยิ่งถ้าตำแหน่งของข้อความสี่เหลี่ยมมันไม่ถูกต้อง(ยังโปรดจำไว้ว่าคุณเคยเป็นการขัดแย้งตำแหน่งมือ Qt.AlignRight | Qt.AlignHCenter จะอยู่เสมองพิจารณาตำแหน่งที่ถูกต้องและค่าปริยายกับนสุดตำแหน่ง)
  • คุณจะใช้เรื่อง วิดเจ็ต แบบอักษร metrics เพื่อตั้งค่าข้อความสี่เหลี่ยมความสูงซึ่ง differs จากเอกสารเป็น metrics ดังนั้นคุณจะจำกัดความสูงของภาพวาด

ไม่เหมือนกันวิดเจ็ต,ร่ำรวยข้อความเครื่องมือแก้ไขข้อความ name ใน Qt มีสองตั้งค่าแบบอักษร:

  • วิดเจ็ต แบบอักษร;
  • คน(ค่าปริยาย) เอกสาร แบบอักษรซึ่งสามารถเป็น overridden โดย QTextOption ในเอกสาร;

เอกสารจะ เสม สืบทอดทางวิดเจ็ตแบบอักษร(หรือโปรแกรมแบบอักษร)สำหรับค่าปริยายแล้วนี่จะยังเกิดขึ้นตอนการตั้งค่าแบบอักษรสำหรับวิดเจ็ตที่ runtime อน,และแม้กระทั่งสำหรับโปรแกรม(เว้นแต่ว่าเป็นอักษรได้ถูกในข้อบังคับของตั้งค่า สำหรับวิดเจ็ต).

การตั้งค่าแบบอักษรสำหรับเครื่องมือแก้ไขโดยปกติแล้วก็คืนดีสำหรับเรียบง่ายในสถานการณ์แต่คุณต้องจำแบบอักษร propagate ดังนั้นลูกๆของวิดเจ็ตจะสืบทอดแบบอักษรเหมือนกัน

ในทางกลับกันการตั้งค่าแบบอักษรปริยายสำหรับเอกสารจะไม่ propagate เพื่อพวกเด็กๆแต่อย่างที่อธิบายอยู่เหนือสามารถเป็น overridden โดยโปรแกรมแบบอักษรแบบถ้ามันเปลี่ยนแปลงที่ runtime.

คนงานง่ายสุดทางออกในกรณีของคุณจะต้องตั้งค่าแบบอักษรสำหรับเครื่องมือแก้ไขวิดเจ็ตแทนของเอกสาร อยู่ทางนี้คุณแน่ใจนะว่า LineNumberArea(ซึ่งเป็นเครื่องมือแก้ไขที่เป็นเด็กคน)จะยังสืบทอดคนเดียวกันแบบอักษรได้ กับเรื่องนี้เข้าใกล้คุณไม่จำเป็นต้องตั้งค่าแบบอักษรของแพนเทอร์อย่างที่มันจะใช้วิดเจ็ตแบบอักษรได้

ในกรณีที่คุณต้องการจะใช้ที่แตกต่างกันแบบอักษรและยังคงทำให้ถูกต้องตำแหน่งคุณต้องพิจารณาถึงกลับมาที่คำถามทั่วๆไปตำแหน่งของการแสดงแบบอักษรที่จะใช้สำหรับเอกสารและใช้อ้างอิงถึงสำหรับกลับมาที่คำถามทั่วๆไปของวิดเจ็ตแบบอักษรได้ เพื่อที่จะทำอย่างนั้นคุณต้องแปลงบล็อคตำแหน่งกับความแตกต่างของ ascent() ขอสองคนแบบอักษร metrics.

2021-11-20 13:08:21

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

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

ดังอยู่ในนี้หมวดหมู่

ดังคำถามอยู่ในนี้หมวดหมู่