Search code examples
pythonqtpyqtqgraphicstextitem

QGraphicsTextItem Setting Text Width For Text Centring


I have a QGraphicsTextItem in which later on I will have to use the toHtml function to retrieve the text and its styling (for writing it into a .ASS file). Currently I use setTextWidth() for the QGraphicsTextItem to allow the text to be in the centre. When setting a text width for the QGraphicsTextItem, the text goes to a new line and this doesn't appear on the toHtml function.

I have found a way to make it display on the toHtml function when a new line was made and what text is in that line, however, I don't like this as I want users to be able to type and the QGraphicsTextItem text width expand with it, whilst having the text centred. If there is a way, then a new line won't be automatically made by the setTextWidth and it will work without having to have a function to check every line on every QGraphicsTextItem and adding a <.br> to it.

I tried using the document().contentsChange() function and adjust the size of the setTextWidth() with it but sometimes it decides to work and then it doesn't. The code below shows my attempt on getting the QGraphicsTextItem to change text width as users type:

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



Solution

  • After trying multiple different things to getting the text to centre, without it creating a new line I found out that you don't even need to set the Text Width to have the text centred you just have to call self.QGraphicsTextItem.adjustSize() whenever the text is changed:

    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, QRectF
    
    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)
    
            # Set text option to prevent word wrap
            text_option = QTextOption()
            text_option.setWrapMode(QTextOption.NoWrap)
            text_option.setAlignment(Qt.AlignCenter)
            self.editable_text.document().setDefaultTextOption(text_option)
    
            self.editable_text.setPlainText('This is an example TEXT')
            self.editable_text.setFont(QFont('Arial', 20))
            self.editable_text.adjustSize()
    
            self.editable_text.document().contentsChange.connect(self.adjust_text_width)
    
            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 adjust_text_width(self):
            self.editable_text.adjustSize()
            
    
    
    app = QApplication(sys.argv)
    main_window = MyMainWindow()
    main_window.resize(800, 500)
    main_window.show()
    sys.exit(app.exec_())