QGraphicsScene添加Widget

简要说明

使用QGraphicsScene的addWidget(QWidget *widget, Qt::WindowFlags wFlangs)可以在场景中添加任意一个继承自QWidget的对象,可以是QPushButton,也可以是自定义的Widget。
在使用时是为要添加的Widget创建一个新的QGraphicsProxyWidget,并将其加入到场景中,返回一个指向这个QGraphicsProxyWidget的指针。此时可以将QGraphicsProxyWidget看做一个QGraphicsItem,可以setPos、setFlags等。

示例介绍

为更直观的展示QGraphicsScene的addWidget功能,附上一个简单示例。此示例的功能是实现一个自定义的Widget在场景的随鼠标拖拽而移动。

开发环境

Qt5.12.4 + VS2017 (64位)

示例代码

1、自定义ActorWidget

#ifndef ACTORWIDGET_H
#define ACTORWIDGET_H

#include <QWidget>

class ActorWidget : public QWidget
{
    Q_OBJECT
public:
    explicit ActorWidget(QWidget *parent = nullptr);

signals:

public slots:
};

#endif // ACTORWIDGET_H
#include "actorwidget.h"

ActorWidget::ActorWidget(QWidget *parent) : QWidget(parent)
{
    this->setStyleSheet("QWidget{background: lightblue;}");
    this->setMouseTracking(true);
}

2、自定义GraphicsScene

#ifndef CUSTOMGRAPHICSSCENE_H
#define CUSTOMGRAPHICSSCENE_H

#include <QGraphicsScene>

class CustomGraphicsScene : public QGraphicsScene
{
public:
    CustomGraphicsScene();

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

private:
    QGraphicsItem *m_pItemSelected; //鼠标选中的QGraphicsItem
    QPointF m_Offset; //鼠标移动的偏移量
    QPointF m_Pressed; //鼠标按下的位置点
    QPointF m_ItemPos; //鼠标选中的QGraphicsItem在场景中的位置
    bool m_bPressed; //鼠标是否按下
};

#endif // CUSTOMGRAPHICSSCENE_H
#include "customgraphicsscene.h"

#include <QGraphicsSceneMouseEvent>
#include <QGraphicsItem>
#include <QGraphicsProxyWidget>

CustomGraphicsScene::CustomGraphicsScene()
    : m_bPressed(false)
{
}

void CustomGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsScene::mousePressEvent(event);

    if(event->button() == Qt::LeftButton)
    {
        m_pItemSelected = nullptr;
        foreach(QGraphicsItem *item, items(event->scenePos()))//循环查找当前鼠标位置点下所有的Item
        {
            if(item->type() == QGraphicsProxyWidget::Type)//判断此Item是否为添加的ActorWidget创建的QGraphicsProxyWidget
            {
                m_bPressed = true;
                m_Pressed = event->scenePos(); //记录此时鼠标在场景中位置点
                m_pItemSelected = item; //选中的Item

                QGraphicsProxyWidget *pProxyWidget = qgraphicsitem_cast<QGraphicsProxyWidget*>(item);
                m_ItemPos = pProxyWidget->scenePos(); //QGraphicsProxyWidget的位置点

                break;
            }
        }
    }
}

void CustomGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsScene::mouseMoveEvent(event);

    if(m_pItemSelected != nullptr)
    {
        if(m_bPressed)
        {
            m_Offset = event->scenePos() - m_Pressed; //鼠标移动的偏移量
            m_pItemSelected->setPos(m_ItemPos + m_Offset); //结合鼠标按下时Item的位置点,重新设置Item的位置点
        }
    }
}

void CustomGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsScene::mouseReleaseEvent(event);

    m_bPressed = false;
    if(m_pItemSelected != nullptr)
    {
        m_pItemSelected = nullptr; //鼠标释放时将选中的Item设为空
    }
}

3、主窗口MainWindow

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>

#include "actorwidget.h"
#include "customgraphicsscene.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    void InitUI();

private:
    Ui::MainWindow *ui;

private:
    CustomGraphicsScene *m_pGraphicsScene;
    ActorWidget *m_pActorWidget;
};

#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QGraphicsProxyWidget>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    InitUI();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::InitUI()
{
    this->resize(540,400);

    m_pGraphicsScene = new CustomGraphicsScene; //自定义的场景
    m_pGraphicsScene->setSceneRect(0,0, ui->graphicsView->width(), ui->graphicsView->height()); //设置场景大小,占据整个QGraphicsView窗口
    ui->graphicsView->setScene(m_pGraphicsScene); //为QGraphicsView设置场景

    m_pActorWidget = new ActorWidget; //自定义的ActorWidget
    m_pActorWidget->resize(400,300);

    QGraphicsProxyWidget *pWidget = m_pGraphicsScene->addWidget(m_pActorWidget); //在场景中添加自定义的ActorWidget,返回一个QGraphicsProxyWidget指针
    pWidget->setPos((ui->graphicsView->width()-m_pActorWidget->width())/2,
                    (ui->graphicsView->height()-m_pActorWidget->height())/2);  //通过QGraphicsProxyWidget指针设置其位置,居中显示
    pWidget->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable); //通过QGraphicsProxyWidget指针设置其可选、可移动、可聚焦
}

效果演示

在这里插入图片描述

  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值