C++ 可拖动的像素映射在图形项的QGraphicsCenter中

C++ 可拖动的像素映射在图形项的QGraphicsCenter中,c++,qt,qt5,qgraphicsitem,qgraphicspixmapitem,C++,Qt,Qt5,Qgraphicsitem,Qgraphicspixmapitem,我有一个12*4网格的场景,有QGraphicsSitems块,当我右键单击这些块时,我有一个contexmenu 可以在块内添加图标我的问题是 我不知道如何才能将这些图标拖动到图形场景中的其他块,我知道有“可拖动图标示例”,但如何将代码实现到图形场景中 这是主窗口 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QGraphicsPathItem> class QGra

我有一个12*4网格的场景,有QGraphicsSitems块,当我右键单击这些块时,我有一个contexmenu 可以在块内添加图标我的问题是 我不知道如何才能将这些图标拖动到图形场景中的其他块,我知道有“可拖动图标示例”,但如何将代码实现到图形场景中

这是主窗口

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsPathItem>
class QGraphicsSceneMouseEvent;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
bool eventFilter(QObject *, QEvent *);
~MainWindow();

private slots:
void showContextMenu(const QPoint&);
void addPixBlock();

private:
Ui::MainWindow *ui;
QGraphicsScene *scene;
QGraphicsItem *itemAt(const QPointF&);

int x;
int y;

QMenu *Menu;
QMenu *Submenu;
QAction *Picture;
QGraphicsPixmapItem* pix;
};
#endif // MAINWINDOW_H
\ifndef主窗口
#定义主窗口
#包括
#包括
QGRAPHICSCENEUSEEVENT类;
名称空间用户界面{
类主窗口;
}
类主窗口:公共QMainWindow
{
Q_对象
公众:
显式主窗口(QWidget*parent=0);
bool事件过滤器(QObject*,QEvent*);
~main窗口();
专用插槽:
void showContextMenu(const QPoint&);
void addPixBlock();
私人:
Ui::MainWindow*Ui;
qgraphicscene*场景;
QGraphicsItem*itemAt(const QPointF&);
int x;
int-y;
QMenu*菜单;
QMenu*子菜单;
QAction*图片;
QGraphicsPixmapItem*pix;
};
#endif//main窗口
mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "block.h"
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
#include <QPainter>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new QGraphicsScene(this) ;
for(int row=-4;row<8;++row)
  for(int column=0;column<4;++column)
{
  Block *b = new Block;
  scene->addItem(b);
  b->setPos(row* 95,column*85);
}
ui->graphicsView->setScene(scene);
scene->installEventFilter(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
QGraphicsItem* MainWindow::itemAt(const QPointF &pos)
{
QList<QGraphicsItem*> items = scene->items(QRectF(pos - QPointF(1,1), 
QSize(3,3)));

foreach(QGraphicsItem *item, items)
     if (item->type() > QGraphicsItem::UserType)
     return item;
 return 0;
  }
 bool MainWindow::eventFilter(QObject *o, QEvent *e)
  {
 QGraphicsSceneMouseEvent *me = (QGraphicsSceneMouseEvent*) e;

 switch ((int) e->type()){

 case QEvent::GraphicsSceneMousePress:{

 switch ((int) me->button()){

  case Qt::RightButton:{

     QGraphicsItem *item = itemAt(me->scenePos());

     if (item && item->type() == Block::Type){
         x=item->scenePos().x();
         y=item->scenePos().y();
        showContextMenu(item->scenePos().toPoint());
      }
   break;
  }
  }
  break;
  }
 }
 return QObject::eventFilter(o, e);
 }
void MainWindow::showContextMenu(const QPoint &pos)
{
Menu= new QMenu("Menu");
Submenu=Menu->addMenu(QIcon(":/img/pix.png"),"Pix");
Picture =Submenu->addAction(QIcon(":/img/pix.png"),"Pix");
connect(Picture, SIGNAL(triggered()), this, SLOT(addPixBlock()));
Menu->exec(QCursor::pos());
}
void MainWindow::addPixBlock()
{
QPixmap pixmap(":/img/pix.png");
pix = scene->addPixmap(pixmap.scaled(70,50));
pix->setPos(x,y);
}
#包括“mainwindow.h”
#包括“ui_main window.h”
#包括“block.h”
#包括
#包括
#包括
#包括
主窗口::主窗口(QWidget*父窗口):
QMainWindow(父级),
用户界面(新用户界面::主窗口)
{
用户界面->设置用户界面(此);
场景=新的Qgraphicscene(此);
for(int row=-4;rowsetPos(row*95,column*85);
}
ui->graphicsView->setScene(场景);
场景->安装事件过滤器(此);
}
MainWindow::~MainWindow()
{
删除用户界面;
}
QGraphicsItem*主窗口::itemAt(const QPointF&pos)
{
QList items=场景->项目(QRectF(pos-QPointF(1,1)),
QSize(3,3));
foreach(QGraphicsItem*项目,项目)
if(item->type()>QGraphicsItem::UserType)
退货项目;
返回0;
}
bool主窗口::事件过滤器(QObject*o,QEvent*e)
{
qgraphicsceneouseevent*me=(qgraphicsceneouseevent*)e;
开关((int)e->type()){
案例QEvent::GraphicsCenemousePress:{
开关((int)me->button()){
案例Qt::RightButton:{
QGraphicsItem*item=itemAt(me->scenePos());
if(项和项->类型()==块::类型){
x=项目->场景().x();
y=项目->场景().y();
showContextMenu(项->场景().toPoint());
}
打破
}
}
打破
}
}
返回QObject::eventFilter(o,e);
}
void主窗口::showContextMenu(常量QPoint和pos)
{
菜单=新的QMenu(“菜单”);
子菜单=菜单->添加菜单(QIcon(:/img/pix.png”),“pix”);
Picture=子菜单->添加操作(QIcon(:/img/pix.png”),“pix”);
连接(图片、信号(已触发())、此、插槽(addPixBlock());
菜单->执行(QCursor::pos());
}
void主窗口::addPixBlock()
{
QPixmap pixmap(:/img/pix.png”);
pix=场景->添加pixmap(pixmap.scaled(70,50));
pix->setPos(x,y);
}
街区

#ifndef BLOCK_H
#define BLOCK_H
#include <QGraphicsPathItem>
class QGraphicsSceneMouseEvent;
class Block : public QGraphicsPathItem
{
public:
enum { Type = QGraphicsItem::UserType + 3 };
int type() const { return Type; }
Block(QGraphicsItem *parent = 0);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget 
*widget);
bool eventFilter(QObject *, QEvent *);
};
#endif // BLOCK_H
#ifndef BLOCK#H
#定义块
#包括
QGRAPHICSCENEUSEEVENT类;
类块:公共QGraphicsPathItem
{
公众:
枚举{Type=QGraphicsItem::UserType+3};
int type()常量{return type;}
块(QGraphicsItem*parent=0);
无效油漆(QPainter*油漆工、常量QStyleOptionGraphicsItem*选项、QWidget
*小部件);
bool事件过滤器(QObject*,QEvent*);
};
#endif//BLOCK_H
Block.cpp

#include "block.h"
#include <QPainter>
#include <QtWidgets>
class QGraphicsSceneMouseEvent;
Block::Block(QGraphicsItem *parent)
         : QGraphicsPathItem(parent)
{
QPainterPath p;
//<->,|,<->,|,roundness
p.addRoundedRect(0,0,80,50, 5, 5);
setPath(p);
setAcceptDrops(true);
setAcceptedMouseButtons(Qt::LeftButton);
}
void Block::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, 
QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
painter->setPen(QPen(QColor(67, 141, 220)));
painter->setBrush(QColor(67, 141, 220,100));
painter->drawPath(path());
}
#包括“block.h”
#包括
#包括
QGRAPHICSCENEUSEEVENT类;
Block::Block(QGraphicsItem*父级)
:QGraphicsPathItem(父级)
{
QPainterPath p;
//,|,,|,圆度
p、 addRoundedRect(0,0,80,50,5,5);
设置路径(p);
setAcceptDrops(真);
setAcceptedMouseButtons(Qt::LeftButton);
}
空块::油漆(QPainter*油漆工,const QStyleOptionGraphicsItem*选项,
QWidget*小部件)
{
Q_未使用(可选)
Q_未使用(小部件)
画师->设置笔(QPen(QColor(67141220));
画家->挫折(QColor(67141220100));
画师->绘图路径(路径());
}

首先,如果您想将一个
QGraphicsPixmapItem
放在另一个项目的顶部,更好的选择是将其设置为您的
父项目

另一方面,我们可以使用事件过滤器,但在这种情况下,更好的选择是实现自定义
qgraphicscene
,当按下左键时,它允许拖动项目,因为我们使用
QDrag
,传递项目的数据,然后覆盖事件
dropEvent
,在那里我们将获得项目建立一个新的父母

graphicscene.h

#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H

#include <QGraphicsScene>

class QMenu;
class QAction;

class GraphicsScene : public QGraphicsScene
{
public:
    using QGraphicsScene::QGraphicsScene;

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    void dropEvent(QGraphicsSceneDragDropEvent *event) override;

private:
    QGraphicsPixmapItem *findPixmapItem(QGraphicsItem *item);
    void createDrag(const QPointF &pos, QWidget *widget, QGraphicsItem *item);
    void showContextMenu(const QPointF &pos);
    void addPixBlock(QGraphicsItem *item);

    QMenu *menu;
    QMenu *submenu;
    QAction *picture;
    QGraphicsPixmapItem *pix;
};

#endif // GRAPHICSSCENE_H
\ifndef graphicscene\u H
#定义图形SCene_H
#包括
QMenu类;
类QAction;
Graphicscene类:公共QGraphicscene
{
公众:
使用QGraphicscene::QGraphicscene;
受保护的:
无效鼠标压力事件(QGraphicsSceneMouseEvent*事件)覆盖;
无效dropEvent(QGraphicsCeneDragDropEvent*事件)覆盖;
私人:
QGraphicsPixmapItem*findPixmapItem(QGraphicsItem*item);
void createDrag(const QPointF&pos、QWidget*小部件、QGraphicsItem*项目);
无效显示上下文菜单(常量QPointF和pos);
作废addPixBlock(QGraphicsItem*项);
QMenu*菜单;
QMenu*子菜单;
QAction*图片;
QGraphicsPixmapItem*pix;
};
#endif//graphicscene_H
graphicscene.cpp

#include "graphicsscene.h"

#include <QDrag>
#include <QGraphicsItem>
#include <QGraphicsSceneMouseEvent>
#include <QMenu>
#include <QMimeData>
#include <QWidget>

void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    auto its =  items(QRectF(event->scenePos() - QPointF(1,1), QSize(3,3)));
    auto val = std::find_if(its.constBegin(), its.constEnd(), [](auto const& it){
        return it->type() > QGraphicsItem::UserType;
    });
    if(val == its.constEnd())
        return;
    if(event->button() == Qt::RightButton){
        showContextMenu(event->scenePos());
    }
    else{
        createDrag(event->scenePos(), event->widget(), *val);
    }

}

void GraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
    QByteArray byteArray = event->mimeData()->data("Item");
    QGraphicsPixmapItem * item = *reinterpret_cast<QGraphicsPixmapItem**>(byteArray.data());
    QGraphicsItem *item_parent = itemAt(event->scenePos(), QTransform());
    item->setParentItem(item_parent);
}

QGraphicsPixmapItem *GraphicsScene::findPixmapItem(QGraphicsItem *item){
    auto chs = item->childItems();
    auto  val = std::find_if(chs.constBegin(), chs.constEnd(), [](auto const& it){
            return static_cast<QGraphicsPixmapItem *>(it) != Q_NULLPTR;
});
    return val == chs.constEnd() ? Q_NULLPTR : static_cast<QGraphicsPixmapItem *>(*val);
}

void GraphicsScene::createDrag(const QPointF &pos, QWidget *widget, QGraphicsItem *item){
    QGraphicsPixmapItem *pix = findPixmapItem(item);
    if(pix == Q_NULLPTR)
        return;
    QByteArray byteArray(reinterpret_cast<char*>(&pix),sizeof(QGraphicsPixmapItem*));
    QDrag *drag = new QDrag(widget);
    QMimeData * mimeData = new QMimeData;
    mimeData->setData("Item",byteArray);
    drag->setMimeData(mimeData);
    drag->setHotSpot(pos.toPoint()-pix->scenePos().toPoint());
    drag->setPixmap(pix->pixmap());
    drag->start();

}

void GraphicsScene::showContextMenu(const QPointF &pos)
{
    QGraphicsItem *item = itemAt(pos, QTransform());
    menu= new QMenu("Menu");
    submenu = menu->addMenu(QIcon(":/img/pix.png"),"Pix");
    picture = submenu->addAction(QIcon(":/img/pix.png"),"Pix");
    connect(picture, &QAction::triggered, [item, this](){
        addPixBlock(item);
    });
    menu->exec(QCursor::pos());
}

void GraphicsScene::addPixBlock(QGraphicsItem *item)
{
    if(findPixmapItem(item))
        return;
    QPixmap pixmap(":/img/pix.png");
    pix = addPixmap(pixmap.scaled(70,50));
    if(pix->parentItem() != item)
        pix->setParentItem(item);
}
#包括“graphicscene.h”
#包括
#包括
#包括
#包括
#包括
#包括
void graphicscene::mousePressEvent(qgraphicscenemouseevent*事件)
{
自动its=items(QRectF(event->scenePos()-QPointF(1,1),QSize(3,3));
auto val=std::find_if(its.constBegin()、its.constEnd()、[](auto const&it){
返回它->type()>QGraphicsItem::UserType;
});
if(val==its.constEnd())
回来
如果(事件->按钮()==Qt::RightButton){
showContextMenu(事件->场景());
}
否则{
创建拖动(事件->场景(),事件->小部件(),*val);
}
}
void graphicscene::dropEvent(QGraphicscendragdropEvent*事件)
{
QByteArray byteArray=事件->mimeData()->数据(“项目”);
QGraphicsPixmapItem*item=*重新解释强制转换(byteArray.data());
QGraphicsItem*item_parent=itemAt(事件->场景(),QTransform());
item->setParentItem(item\u parent);
}
QGraphicsPixmapItem*Graphicscene::findPixmapItem(QGraphicsItem*ite