Search code examples
c++qtqt5qgraphicsitemqlabel

QLabel not resizing after changing its text


I have a QLabel centered in a custom QGraphicsPolygonItem and I'm using a QAction to change the labels text, but when the text changes the label size doesn't change, I want it to resize to the size of the new text and keep it centered. Here's my custom item constrctor:

DiagramItem::DiagramItem(DiagramType diagramType, QMenu *contextMenu,
         QGraphicsItem *parent)
: QGraphicsPolygonItem(parent){
QGraphicsProxyWidget* pMyProxy = new QGraphicsProxyWidget(this);
QLabel *label = new QLabel();
label->setText(QString("I AM A SQARE DADADA"));
label->setTextInteractionFlags(Qt::TextEditorInteraction);
label->setStyleSheet("QLabel { background-color : red; color : blue; }");
pMyProxy->setWidget(label);
pMyProxy->setPos(this->boundingRect().center()-label->rect().center());
...

Here's the slot I'm using to change the text of the label:

void MainWindow::setItemLabel(){
if(!scene->selectedItems().isEmpty())
{
    auto *item = scene->selectedItems().first();
    if(!(item->childItems().isEmpty()))
    {
        auto proxy = static_cast<QGraphicsProxyWidget *>(item->childItems().first());
        if(proxy)
        {
            auto label = qobject_cast<QLabel*>(proxy->widget());
            if(label)
            {
                QDialog *diag = new QDialog(this);
                QComboBox *box = new QComboBox();
                QLineEdit *lt = new QLineEdit();
                QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
                                                                    | QDialogButtonBox::Cancel);
                QVBoxLayout *mainLayout = new QVBoxLayout();
                connect(buttonBox, SIGNAL(accepted()), diag, SLOT(accept()));
                connect(buttonBox, SIGNAL(rejected()), diag, SLOT(reject()));
                mainLayout->addWidget(lt);
                mainLayout->addWidget(buttonBox);

                diag->setLayout(mainLayout);
                if(diag->exec() == QDialog::Accepted){
                    QString *usrInpt = new QString();
                    *usrInpt = lt->text();
                    label->rect().setWidth(usrInpt->length());
                    label->setText(*usrInpt);
                }
            }
        }
    }
}

Here's what I'm getting as a result, this is before triggering the slot above: BeforeSlotTriggere And here's what I'm getting after the slot is triggered: AfterSlotTriggered

This line isn't doing anything too, and I have no idea why:

label->rect().setWidth(usrInpt->length());

What am I missing?


Solution

  • You can adjust the size of the QLabel with adjustSize(), but even so the QGraphicsProxyWidget will not change its size causing the problem to persist, to correct we must overwrite boundingRect() and return the appropriate size, in addition to this the way you set the text does not is appropriate, if you are creating a class that has the label inside you could create a setText() method that updates the QLabel without the need to write a lot of code:

    class GraphicsProxyWidget: public QGraphicsProxyWidget{
    public:
        using QGraphicsProxyWidget::QGraphicsProxyWidget;
        QRectF boundingRect() const{
            if(widget())
                return QRectF(widget()->rect());
            return QGraphicsProxyWidget::boundingRect();
        }
    };
    
    class DiagramItem: public QGraphicsPolygonItem{
        QLabel *label;
        GraphicsProxyWidget *pMyProxy ;
    public:
        explicit DiagramItem(DiagramType diagramType, QMenu *contextMenu, QGraphicsItem *parent=nullptr):QGraphicsPolygonItem(parent) {
            label = new QLabel;
            pMyProxy = new GraphicsProxyWidget(this);
            pMyProxy->setWidget(label);
            label->setTextInteractionFlags(Qt::TextEditorInteraction);
            label->setStyleSheet("QLabel { background-color : red; color : blue; }");
            setText("I AM A SQARE DADADA");
            ...
        }
        void setText(const QString & text){
           label->setText(text);
           label->adjustSize();
           pMyProxy->setPos(boundingRect().center()-label->rect().center());
        }
    };
    

    and then the setItemLabel method would look like this:

    void MainWindow::setItemLabel(){
        if(!scene->selectedItems().isEmpty())
        {
            auto *item = scene->selectedItems().first();
            DiagramItem *it = static_cast<DiagramItem *>(item);
            if(it){
                QDialog *diag = new QDialog(this);
                QComboBox *box = new QComboBox();
                QLineEdit *lt = new QLineEdit();
                QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
                                                                   | QDialogButtonBox::Cancel);
                QVBoxLayout *mainLayout = new QVBoxLayout();
                connect(buttonBox, SIGNAL(accepted()), diag, SLOT(accept()));
                connect(buttonBox, SIGNAL(rejected()), diag, SLOT(reject()));
                mainLayout->addWidget(lt);
                mainLayout->addWidget(buttonBox);
    
                diag->setLayout(mainLayout);
                if(diag->exec() == QDialog::Accepted){
                    it->setText(lt->text())
                }
            }
        }
    }
    

    Example:

    #include <QApplication>
    #include <QGraphicsProxyWidget>
    #include <QGraphicsView>
    #include <QLabel>
    #include <QTimer>
    
    class GraphicsProxyWidget: public QGraphicsProxyWidget{
    public:
        using QGraphicsProxyWidget::QGraphicsProxyWidget;
        QRectF boundingRect() const{
            if(widget())
                return QRectF(widget()->rect());
            return QGraphicsProxyWidget::boundingRect();
        }
    };
    
    class DiagramItem: public QGraphicsPolygonItem{
        QLabel *label;
        GraphicsProxyWidget *pMyProxy ;
    public:
        explicit DiagramItem(QGraphicsItem *parent=nullptr):QGraphicsPolygonItem(parent) {
            label = new QLabel;
            pMyProxy = new GraphicsProxyWidget(this);
            pMyProxy->setWidget(label);
            label->setTextInteractionFlags(Qt::TextEditorInteraction);
            label->setStyleSheet("QLabel { background-color : red; color : blue; }");
            setText(QString("I AM A SQARE DADADA"));
            setBrush(Qt::green);
        }
        void setText(const QString & text){
           label->setText(text);
           label->adjustSize();
           pMyProxy->setPos(boundingRect().center()-label->rect().center());
        }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QGraphicsView w;
        QGraphicsScene *scene = new QGraphicsScene;
        w.setScene(scene);
        auto it = new DiagramItem;
        QPolygonF myPolygon({QPointF(-120, -80), QPointF(-70, 80),
                             QPointF(120, 80), QPointF(70, -80),
                             QPointF(-120, -80)});
        it->setPolygon(myPolygon);
        scene->addItem(it);
        QTimer::singleShot(1000, [it](){
            it->setText("some text");
        });
        w.show();
        return a.exec();
    }
    

    enter image description here

    enter image description here