Home > OS >  Get the position of a QWidget that is inside a QGraphicsItem
Get the position of a QWidget that is inside a QGraphicsItem

Time:04-24

I have a QWidget with a QPushButton, at the same time, this QWidget is embedded into a QGraphicsItem, which is inside a QGraphicsScene.

I need to draw a line between two of those QGraphicsItems pointing to the QPushButton. For that, I need to get the position of the QPushButton. It looks like this:

picture

I tried getting the position of the QPushButton inside the constructor of the QGraphicsItem, but it returns 0,0. I guess this is the position of the button inside the QWidget. I guess what I need is a way to get the position on the screen.

Minimal Example: Simplified as much as possible. QWidget:

NodeFrame::NodeFrame()
{
  setFixedSize(200,80);
  setStyleSheet("QFrame { background-color: #2e4076; }");
  
  // Creates and add a QPushButton to the frame.
  // I need the position of this button on the QGraohicsScene
  auto button = new QPushButton("B");
  button->setFixedSize(40,20);
  
  auto layout = new QHBoxLayout();
  layout->addWidget(button);
  setLayout(layout);
}

QGraphicsItem:

class Node : public QGraphicsItem
{
public:
  Node();
  QRectF boundingRect() const override;
  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
};

Node::Node()
{
  setFlag(ItemIsMovable);

  // Create a GraphicsProxyWidget to insert the nodeFrame into the scene
  auto proxyWidget = new QGraphicsProxyWidget(this);
  auto frame = new NodeFrame();
  proxyWidget->setWidget(frame);
  // Center the widget(frame) at the center of the QGraphicsItem
  proxyWidget->setPos(boundingRect().center() - proxyWidget->boundingRect().center());
}

QRectF Node::boundingRect() const
{
  return QRectF(-10, -10, 280, 150);
}

void Node::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
  QPainterPath path;
  path.addRoundedRect(boundingRect(), 10, 10);
  painter->drawPath(path);
}

Main:

int main(int argc, char* argv[])
{
  QApplication app(argc, argv);
  
  // Create scene and view
  auto scene = new QGraphicsScene();
  auto view = new QGraphicsView(scene);
  
  view->setMinimumSize(800, 800);
  
  // Create the QGraphicsItem and add it to the scene
  auto item = new Node();
  scene->addItem(item);
  item->setPos(-50, -50);
  
  // Show the the view
  view->show();
  return app.exec();
}

CodePudding user response:

In nodeframe.cpp I add one function getButtonRect() :

#ifndef NODEFRAME_H
#define NODEFRAME_H

#include <QWidget>
#include <QPushButton>
#include <QRect>


class NodeFrame: public QWidget
{
public:
    NodeFrame();

    QRect  getButtonRect();

private:
    QPushButton *button;
    QHBoxLayout *layout;

};

#endif // NODEFRAME_H

nodeframe.cpp

#include "nodeframe.h"

NodeFrame::NodeFrame()
{
    setFixedSize(200, 80);
    setStyleSheet("QFrame { background-color: #2e4076; }");

    // Creates and add a QPushButton to the frame.
    // I need the position of this button on the QGraohicsScene
    button = new QPushButton("B");
    button->setFixedSize(40, 20);

    layout = new QHBoxLayout();
    layout->addWidget(button);
    setLayout(layout);
}

QRect  NodeFrame::getButtonRect()
{
    return layout->itemAt(0)->geometry();
}

and in Node pass this function to main.cpp because QGraphicsView is there:

node.cpp:

#include "node.h"

#include <QGraphicsProxyWidget>
#include <QPainter>

Node::Node()
{
    setFlag(ItemIsMovable);

    // Create a GraphicsProxyWidget to insert the nodeFrame into the scene
    auto  proxyWidget = new QGraphicsProxyWidget(this);
    frame = new NodeFrame();
    proxyWidget->setWidget(frame);
    // Center the widget(frame) at the center of the QGraphicsItem
    proxyWidget->setPos(boundingRect().center() - proxyWidget->boundingRect().center());
}

QRectF  Node::boundingRect() const
{
    return QRectF(-10, -10, 280, 150);
}

void  Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPainterPath  path;

    path.addRoundedRect(boundingRect(), 10, 10);
    painter->drawPath(path);
}

QRect  Node::getButtonRect()
{
    return frame->getButtonRect();
}

main.cpp

#include "node.h"

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>

int  main(int argc, char *argv[])
{
    QApplication  app(argc, argv);

    // Create scene and view
    auto  scene = new QGraphicsScene();
    auto  view  = new QGraphicsView(scene);

    view->setMinimumSize(800, 800);

    // Create the QGraphicsItem and add it to the scene
    auto  item = new Node();
    scene->addItem(item);
    item->setPos(0, 0);

// qDebug() << "RECT bottomLeft= " << view->mapToScene(item->getButtonRect().bottomLeft());
// qDebug() << "RECT bottomRight= " << view->mapToScene(item->getButtonRect().bottomRight());
// qDebug() << "RECT topLeft= " << view->mapToScene(item->getButtonRect().topLeft());
// qDebug() << "RECT topRight= " << view->mapToScene(item->getButtonRect().topRight());

    auto  btnRect = item->getButtonRect();
    auto  ellipse = new QGraphicsEllipseItem(QRect(view->mapToGlobal(btnRect.center()).x(), view->mapToGlobal(btnRect.center()).y(), 40, 40));
    qDebug() << "Center" << view->mapToGlobal(btnRect.center());
    scene->addItem(ellipse);

    // Show the the view
    view->show();

    return app.exec();
}

enter image description here

enter image description here

  • Related