我有一个 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_())
我尝试按照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_())