获取 QGraphicsItem 内的 QWidget 的位置

Get the position of a QWidget that is inside a QGraphicsItem

我有一个带有 QPushButton 的 QWidget,同时,这个 QWidget 被嵌入到 QGraphicsItem 中,它位于 QGraphicsScene 中。

我需要在两个指向 QPushButton 的 QGraphicsItems 之间画一条线。为此,我需要获得 QPushButton 的位置。它看起来像这样:

我尝试在 QGraphicsItem 的构造函数中获取 QPushButton 的位置,但它 returns 0,0。我猜这是 QWidget 中按钮的位置。我想我需要的是一种获取屏幕位置的方法。

最小示例:尽可能简化。 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);
}

主要:

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();
}

nodeframe.cpp中我添加了一个函数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();
}

并在 Node 中将此函数传递给 main.cpp 因为 QGraphicsView 在那里:

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();
}