QGraphicsTextItem 居中问题

问题描述 投票:0回答:1

我有一个 QGraphicsTextItem,在其中编辑了该类,以便在格式化新行时可以将文本显示在中心。我当前面临的问题是我无法调用原始类,因为它将创建另一个不居中的文本元素。另外,我无法使用 html 样式来居中,因为我需要知道新行何时被格式化,并且使用 html 选项,当它达到其最大宽度时,它会创建一个新行,但您无法将新行检索为
(至少我没能做到),当使用 toHtml 函数时。

我尝试在用户突出显示文本背景时设置文本背景的格式,但由于我将文本居中,所以我只能在不居中文本的情况下突出显示。我也尝试抓住鼠标位置并像这样突出显示它,但它没有突出显示整个角色。

这是尝试居中并突出显示的代码:

import sys
from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView, QGraphicsTextItem, QStyle
from PyQt5.QtGui import QPainter, QPen, QColor, QFont, QTextCursor, QTextLayout, QAbstractTextDocumentLayout, QPalette, QTextCharFormat, QBrush, QTextOption
from PyQt5.QtCore import Qt, QRectF

class CenteredTextItem(QGraphicsTextItem):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setTextInteractionFlags(Qt.TextEditorInteraction)
        self.setFlags(QGraphicsTextItem.ItemIsSelectable | QGraphicsTextItem.ItemIsMovable | QGraphicsTextItem.ItemIsFocusable)
        
        # Set text alignment to center
        option = QTextOption()
        option.setAlignment(Qt.AlignCenter)
        self.document().setDefaultTextOption(option)

    def paint(self, painter, option, widget):
        painter.save()

        painter.setFont(self.font())
        bounding_rect = self.boundingRect()

        # Store original formatting of selected text
        original_format = None
        if self.textCursor().hasSelection():
            cursor = self.textCursor()
            start = cursor.selectionStart()
            end = cursor.selectionEnd()
            original_format = cursor.charFormat()

            # Apply highlight to selected text
            highlight_color = QColor(Qt.yellow)  # Change this to your desired highlight color
            format = QTextCharFormat(original_format)  # Preserve original formatting
            format.setBackground(QBrush(highlight_color))
            cursor.setPosition(start)
            cursor.setPosition(end, QTextCursor.KeepAnchor)
            cursor.mergeCharFormat(format)

        # Draw the document
        self.document().drawContents(painter)

        # Restore original formatting
        if original_format is not None:
            cursor = self.textCursor()
            start = cursor.selectionStart()
            end = cursor.selectionEnd()
            cursor.setPosition(start)
            cursor.setPosition(end, QTextCursor.KeepAnchor)
            cursor.setCharFormat(original_format)

        # Draw the bounding rectangle
        painter.translate(-bounding_rect.topLeft())
        painter.setPen(QPen(Qt.black, 1, Qt.SolidLine))
        painter.drawRect(bounding_rect)

        # Draw focus rectangle if item has focus
        if option.state & QStyle.State_HasFocus:
            pen = QPen(Qt.DashLine)
            painter.setPen(pen)
            painter.drawRect(bounding_rect)

        painter.restore()

class MyGraphicsView(QGraphicsView):
    def __init__(self):
        super().__init__()
        scene = QGraphicsScene(self)
        self.setScene(scene)
        self.setSceneRect(0, 0, 400, 300)

        self.editable_text = CenteredTextItem()

        # Previous Background to check if it goes back
        cursor = self.editable_text.textCursor()
        cursor.select(QTextCursor.Document)
        format = QTextCharFormat()
        format.setBackground(QBrush(Qt.red))
        cursor.mergeCharFormat(format)
        self.editable_text.setTextCursor(cursor)



        self.editable_text.setPlainText('Centered Text ssssssssssssssssssssssssssssssssssssssssssssssssssssss test')
        self.editable_text.setFont(QFont('Arial', 20))

        scene.addItem(self.editable_text)

app = QApplication(sys.argv)
view = MyGraphicsView()
view.resize(800, 500)
view.show()
sys.exit(app.exec_())
qt pyqt qgraphicstextitem
1个回答
0
投票

我尝试按照musicamante的建议进行操作,但无法使用 document().contentsChange() 信号动态增加它,因此我必须检查有多少行,并查看该行上有哪些文本来添加前面有“<.br>”。我还没有真正测试过那么多,但它可以工作,但不如动态改变大小那么有效:



import sys, re
from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsScene, QGraphicsView, QGraphicsTextItem, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtGui import QFont, QTextOption
from PyQt5.QtCore import Qt

class TextItem(QGraphicsTextItem):
    def __init__(self, parent=None):
        super().__init__(parent)
        # Set text alignment to center
        option = QTextOption()
        option.setAlignment(Qt.AlignCenter)
        self.document().setDefaultTextOption(option)

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        # Create the central widget and layout for the window
        self.central_widget = QWidget()
        self.layout = QVBoxLayout(self.central_widget)

        # Create QGraphicsView and QGraphicsScene
        self.view = QGraphicsView()
        self.scene = QGraphicsScene(self)
        self.view.setScene(self.scene)
        self.view.setSceneRect(0, 0, 400, 300)

        self.editable_text = TextItem()
        self.editable_text.setTextInteractionFlags(Qt.TextEditorInteraction)
        self.editable_text.setFlags(QGraphicsTextItem.ItemIsSelectable | QGraphicsTextItem.ItemIsMovable | QGraphicsTextItem.ItemIsFocusable)
        self.editable_text.setTextWidth(self.view.scene().width())
        self.editable_text.adjustSize()

        self.editable_text.setPlainText('Centered Text test')
        self.editable_text.setFont(QFont('Arial', 20))

        self.scene.addItem(self.editable_text)


        # Add the QGraphicsView to the layout
        self.layout.addWidget(self.view)

        # Add a button to save text as HTML
        self.save_button = QPushButton("Save as HTML")
        self.save_button.clicked.connect(self.save_as_html)
        self.layout.addWidget(self.save_button)

        # Set the central widget of the QMainWindow
        self.setCentralWidget(self.central_widget)

    def save_as_html(self):
        # Get the current HTML from the document
        existing_html = self.editable_text.document().toHtml()

        # Retrieve the wrapped lines with <br> tags
        wrapped_lines = self.get_wrapped_lines()
        html_with_br = "<br>".join(wrapped_lines)

        # Replace the content inside the <p> tags with the new content
        # Find all <p> tags
        paragraphs = re.findall(r'(<p[^>]*>)(.*?)(</p>)', existing_html, re.DOTALL)

        # Combine the new content into the existing HTML, replacing old content inside <p> tags
        new_html = existing_html
        for opening_tag, old_content, closing_tag in paragraphs:
            new_html = new_html.replace(f'{opening_tag}{old_content}{closing_tag}', f'{opening_tag}{html_with_br}{closing_tag}', 1)

        # Write the updated HTML content to the file
        with open("text_files.html", "w") as file:
            file.write(new_html)

        print("HTML file updated successfully.")



    def get_wrapped_lines(self):
        # Initialize a list to store lines
        lines = []

        # Get the text document
        text_document = self.editable_text.document()

        # Iterate through the blocks in the document
        block = text_document.begin()
        while block.isValid():
            # Get the block's layout
            block_layout = block.layout()
            
            # Iterate through lines in the block's layout
            for i in range(block_layout.lineCount()):
                line = block_layout.lineAt(i)
                # Use the block's text to find the text in this line
                line_start = line.textStart()
                line_end = line_start + line.textLength()
                lines.append(block.text()[line_start:line_end])
            
            # Move to the next block
            block = block.next()
        
        return lines

app = QApplication(sys.argv)
main_window = MyMainWindow()
main_window.resize(800, 500)
main_window.show()
sys.exit(app.exec_())
© www.soinside.com 2019 - 2024. All rights reserved.