Получить позицию QWidget внутри QGraphicsItem

У меня есть QWidget с QPushButton, в то же время этот QWidget встроен в QGraphicsItem, который находится внутри QGraphicsScene.

Мне нужно провести линию между двумя из этих QGraphicsItems, указывающими на QPushButton. Для этого мне нужно получить позицию QPushButton. Это выглядит так:

picture

Я попытался получить позицию QPushButton внутри конструктора QGraphicsItem, но он возвращает 0,0. Я предполагаю, что это положение кнопки внутри QWidget. Я предполагаю, что мне нужен способ получить положение на экране.

Минимальный пример: максимально упрощен. Qвиджет:

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

Предоставьте минимальный воспроизводимый пример, чтобы мы могли запустить и протестировать его.

Parisa.H.R 23.04.2022 09:15

@ Parisa.H.R Спасибо за ваш ответ. Готово!

Tac 23.04.2022 18:24
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
1
2
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В 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:

узел.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

Спасибо. Он получает позицию, но, похоже, это его позиция внутри родительского QWidget или что-то еще. Следуя вашему примеру, я добавил QGraphicsEllipseItem или круг в центр QRect кнопки. Я ожидал, что круг будет расположен в центре кнопки, но это не так: i.gyazo.com/51b121821a68d66fffc3079b7ad54966.gif Каким-то образом эту позицию нужно сопоставить со сценой или представлением.

Tac 23.04.2022 19:31

возможно, макет делает это возможным. Я отредактировал свой ответ, mapToScene дал вам позицию сцены

Parisa.H.R 23.04.2022 19:59

Мы приближаемся. Это мой вывод: Положение кнопки: QPoint(-272633456,32766) Сопоставленное положение кнопки: QPointF(-2.72634e+08,32766) Теперь это выглядит по-другому. Однако, когда я добавляю круг в эту позицию (в main), круг находится далеко от кнопки: i.gyazo.com/2551ad45b7037021e4505afed6f30f49.gif Обратите внимание, что я использую центр прямоугольника кнопки в качестве позиции после сопоставления его со сценой, как в вашем примере.

Tac 23.04.2022 20:24

mapToGlobal() приближает его, но еще не достиг: i.gyazo.com/ad97ce948d23d6ac023d362d4b02c32a.gif

Tac 23.04.2022 20:38

@Tac Я думаю, что QHBoxLayout создает проблемы, мы должны получить от него кнопку layout->itemAt(0)->geometry(); Эта точка находится в центре кнопки, которую я печатаю.

Parisa.H.R 23.04.2022 20:53

и мы не должны item->setPos(-50, -50);

Parisa.H.R 23.04.2022 21:04

В порядке. Теперь я получаю геометрию кнопки прямо из макета, как вы это сделали и убрали item->setPos(-50, -50). Если я не использую mapToScene, я получаю что-то близкое к вашему результату: i.gyazo.com/826470a15f5c8af1246a16b478b47f93.gif Но это действительно центр? Я думал, что это будет точно в центре кнопки. Но если я нанесу его на карту, он уйдет дальше: i.gyazo.com/8f22859352f7e2c6e386280649e026cd.gif

Tac 23.04.2022 21:24

Используйте mapToGlobal, а не mapToScene

Parisa.H.R 23.04.2022 21:25

Я также пытался сначала сопоставить его с элементом QGraphicsItem::mapToItem внутри Node`` (item), then mapping it to scene in main```, но результат также неверен.

Tac 23.04.2022 21:26

Вы тестировали QRect(view->mapToGlobal(btnRect.center()).x(), view->mapToGlobal(btnRect.center()).y(), 40, 40)? Потому что, когда я добавляю свою картинку, кажется, что она показывает центр кнопки @Tac

Parisa.H.R 23.04.2022 21:28

Извините, я не заметил, что вы обновили ответ. Теперь я понимаю и получаю те же результаты, что и вы: i.gyazo.com/85c94863d66240a63ed760a5c50f92da.gif Итак, центр прямоугольника кнопки находится в углу? Я также заметил, что чем меньше я получаю круг, тем дальше он уходит от кнопки: i.gyazo.com/8fd392f53147007e44b0e046bdd6b936.gif

Tac 23.04.2022 21:57

Точка верна, она находится в центре, вы можете проверить нижний правый или нижний левый или . .. вы можете видеть, что точка правильная, но наша ширина и высота меняются. Я установил 40 * 40, ваш i.gyazo.com/85c94863d66240a63ed760a5c50f92da.gif правильный

Parisa.H.R 23.04.2022 22:03

Ну, мы нашли центр, и это был вопрос. Я думаю, что-то еще отключено. Большое спасибо за ваше время. Я узнал довольно много с этим.

Tac 23.04.2022 22:17

Добро пожаловать, я тоже

Parisa.H.R 23.04.2022 22:20

Другие вопросы по теме