Search code examples
c++qtqgraphicsitemqlabel

Align QLabel with custom QGraphicsItem


I'm new to Qt programming and I want to align a QLabel with a custom QGraphicsItem i created. Here's inside my custom item constructor:

QGraphicsProxyWidget* pMyProxy = new QGraphicsProxyWidget(this);
QLabel *label = new QLabel();
label->setText("Some Text");
pMyProxy->setWidget(label);
label->setAlignment(Qt::AlignLeft);

the last line seems to have no effect whether its AlignLeft, Center, or Right. myItem is a custom rectangle, and I'd like the label to be centered inside the rectangle, as it is the first word of label is being centered at the rectangle instead of the center of the label.

Please help


Solution

  • When you add a widget through a proxy, the proxy is the child of the initial item so its position will be relative to it and by default the position is (0, 0), so you see that although you set an alignment does not change, what you must do to place it in the center through setPos():

    #include <QApplication>
    #include <QGraphicsProxyWidget>
    #include <QGraphicsView>
    #include <QLabel>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QGraphicsView w;
        QGraphicsScene *scene = new QGraphicsScene;
    
        QGraphicsRectItem *item = new QGraphicsRectItem;
        item->setRect(QRect(0, 0, 200, 200));
        item->setBrush(Qt::red);
        scene->addItem(item);
        QGraphicsProxyWidget *pMyProxy = new QGraphicsProxyWidget(item);
        QLabel *label = new QLabel();
        label->setText("Some Text");
        pMyProxy->setWidget(label);
        pMyProxy->setPos(item->boundingRect().center()-label->rect().center());
        w.setScene(scene);
        w.show();
    
        return a.exec();
    }
    

    enter image description here


    Assuming this is the item, you should do the following:

    QGraphicsProxyWidget *pMyProxy = new QGraphicsProxyWidget(this);
    QLabel *label = new QLabel();
    label->setText("Some Text");
    pMyProxy->setWidget(label);
    pMyProxy->setPos(boundingRect().center()-label->rect().center());
    

    If you want to access the widget regarding the item you must follow the children tree:

    QGraphiscScene
    └── QGraphiscItem
        └── (children)
            QGraphicsProxyWidget
            └── (widget)
                QLabel
    

    Example:

    main.cpp

    #include <QApplication>
    #include <QGraphicsProxyWidget>
    #include <QGraphicsView>
    #include <QLabel>
    #include <QTimer>
    #include <QDebug>
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QGraphicsView w;
        QGraphicsScene *scene = new QGraphicsScene;
    
        QGraphicsRectItem *item = new QGraphicsRectItem;
        item->setRect(QRect(0, 0, 200, 200));
        item->setBrush(Qt::red);
        scene->addItem(item);
        item->setFlag(QGraphicsItem::ItemIsSelectable, true);
        item->setFlag(QGraphicsItem::ItemIsMovable, true);
        QGraphicsProxyWidget *pMyProxy = new QGraphicsProxyWidget(item);
        QLabel *label = new QLabel();
        label->setText("Some Text");
        pMyProxy->setWidget(label);
        pMyProxy->setPos(item->boundingRect().center()-label->rect().center());
        w.setScene(scene);
        QTimer timer;
        QObject::connect(&timer, &QTimer::timeout, [&](){
            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){
                            label->setText(QString("x: %1, y: %2").arg(item->pos().x()).arg(item->pos().y()));
                        }
                    }
                }
            }
        });
        timer.start(100);
        w.show();
    
        return a.exec();
    }