我有一个 QGraphicsTextxtItem,稍后我将不得不使用 toHtml 函数来检索文本及其样式(用于将其写入 .ASS 文件)。目前,我对 QGraphicsTextItem 使用 setTextWidth() 来允许文本位于中心。当为 QGraphicsTextItem 设置文本宽度时,文本会换行,并且不会出现在 toHtml 函数中。
我找到了一种方法,可以在创建新行以及该行中的文本时将其显示在 toHtml 上,但是,我不喜欢这样,因为我希望用户能够键入并且 QGraphicsTextItem 文本宽度展开与它,同时使文本居中。如果有办法,那么 setTextWidth 不会自动创建新行,并且无需使用函数来检查每个 QGraphicsTextItem 上的每一行并向其添加
即可工作。
我尝试使用 document().contentsChange() 函数并用它调整 setTextWidth() 的大小,但有时它决定工作,然后又不行。下面的代码显示了我尝试让 QGraphicsTextItem 在用户键入时更改文本宽度:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsScene, QGraphicsView, QGraphicsTextItem, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtGui import QFont
from PyQt5.QtCore import Qt
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 = QGraphicsTextItem()
self.editable_text.setTextInteractionFlags(Qt.TextEditorInteraction)
self.editable_text.setFlags(QGraphicsTextItem.ItemIsSelectable | QGraphicsTextItem.ItemIsMovable | QGraphicsTextItem.ItemIsFocusable)
self.editable_text.setHtml(f'<div style="text-align: center;">This is an example TEXT</div>')
self.editable_text.setTextWidth(self.view.scene().width())
self.editable_text.adjustSize()
self.editable_text.document().contentsChange.connect(self.centre_text)
self.editable_text.setFont(QFont('Arial', 20))
self.scene.addItem(self.editable_text)
# Add the QGraphicsView to the layout
self.layout.addWidget(self.view)
# Set the central widget of the QMainWindow
self.setCentralWidget(self.central_widget)
def centre_text(self):
self.editable_text.setTextWidth(self.editable_text.textWidth())
print(self.editable_text.textWidth())
self.editable_text.adjustSize()
app = QApplication(sys.argv)
main_window = MyMainWindow()
main_window.resize(800, 500)
main_window.show()
sys.exit(app.exec_())
我尝试按照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_())