Widget类发送
setDragEnabled(true)函数以使该部件能接受拖放事件.
在widget类重写mousePressEvent()或mouseMoveEvent()函数中启动拖放,记住启动拖放就是调用QDrag对象的exec()函数,在此步把需要拖动的数据保存在QMimeData对象中。
QDrag *drag=new QDrag(this);
QMimeData *mimeData=new QMimeData;
mimeData->setText(currentItem()->text());
mimeData->setData("application/Units.list", encodedData);
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction|Qt::MoveAction);
//或者是调用setData发送自定义数据
void MyListWidget::mouseMoveEvent(QMouseEvent *event)
{
if (!(event->buttons()&Qt::LeftButton))
return;
if ((event->pos() - m_dragPosition).manhattanLength() < QApplication::startDragDistance())
return;
if (!m_dragItem)
return;
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
QString strtext = currentItem()->text();
if (strtext.isEmpty())
{
int row = currentRow() - 2;
QByteArray encodedData;
QDir dir1;
QString strdir = dir1.currentPath();
QString strfile = strdir + "/svg/" + m_strList[row];
QDataStream stream(&encodedData, QIODevice::WriteOnly);
{
QPixmap pixmap(strfile);
stream << pixmap;
}
mimeData->setData("draglist", encodedData);
}
else
{
mimeData->setData("draglist", strtext.toUtf8());
}
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
使用场景类接收拖拽
调用setAcceptDrops(true).使能接收数据。
主要重写dragEnterEvent、dragMoveEvent、dropEvent。
void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override;
void dragMoveEvent(QGraphicsSceneDragDropEvent *event) override;
void dropEvent(QGraphicsSceneDragDropEvent *event) override;
![](https://img-blog.csdnimg.cn/img_convert/8a5d50c51c91cc0789f033bf388cb3e9.png)
void MyGraphicsScene::createRect(const QPointF &pt)
{
MyGraphicsRectItem *item=new MyGraphicsRectItem;
item->setPos(pt);
qDebug() << "rect pos:" << pt.x() << pt.y();
item->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
addItem(item);
}
void MyGraphicsScene::createLine(const QPointF &pt)
{
MyGraphicsLineItem *item=new MyGraphicsLineItem;
item->setPos(pt);
item->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
addItem(item);
}
void MyGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
if(event->mimeData()->hasFormat("text/plain")){
event->acceptProposedAction();
}
}
void MyGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
// QGraphicsScene::dropEvent(event);
if (event->mimeData()->hasFormat("text/plain"))
{
QString text=event->mimeData()->text();
if(text==tr("直线"))
{
createLine(event->scenePos());
}
else if(text==tr("矩形"))
{
createRect(event->scenePos());
}
else{
}
event->acceptProposedAction();
}
}
void MyGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
event->accept();
}
测试发现:item在视图存放的位置有些问题?前面位置没法固定,添加多了就ok.
使用视图类来处理拖拽的接收(推荐使用这种办法)
使用视图类可以保证item在视图存放的位置就是鼠标的位置。
场景类就不用重写dragEnterEvent、dragMoveEvent、dropEvent。
视图类调用setAcceptDrops(true)允许接收。
视图类重写dragEnterEvent、dragMoveEvent、dropEvent。
#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H
#include <QObject>
#include <QGraphicsView>
class MyGraphicsView : public QGraphicsView
{
public:
MyGraphicsView(QWidget *parent=0);
~MyGraphicsView();
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event) ;
void dropEvent(QDropEvent *event);
};
#endif // MYGRAPHICSVIEW_H
#include "mygraphicsview.h"
#include "mygraphicsscene.h"
#include <QDragEnterEvent>
#include <QMimeData>
#include <QDebug>
#include <QMouseEvent>
#include <QPoint>
#if _MSC_VER >=1600
#pragma execution_character_set("utf-8")
#endif
MyGraphicsView::MyGraphicsView(QWidget *parent):
QGraphicsView(parent)
{
}
MyGraphicsView::~MyGraphicsView()
{
}
void MyGraphicsView::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasFormat("text/plain")){
event->acceptProposedAction();
qDebug() << "view dragEnterEvent";
}
QGraphicsView::dragEnterEvent(event);
}
void MyGraphicsView::dragMoveEvent(QDragMoveEvent *event)
{
qDebug() << "view dragMoveEvent";
event->acceptProposedAction();
}
void MyGraphicsView::dropEvent(QDropEvent *event)
{
qDebug() << "view dropevent";
if (event->mimeData()->hasFormat("draglist"))
{
QByteArray itemData = event->mimeData()->data("draglist");
QString strText = itemData;
MyGraphicsScene *scene=(MyGraphicsScene*)this->scene();
QPoint po = event->pos();
qDebug() << "dropevent pos:"<< po.x() << po.y() ;
if (strText == "直线")
{
scene->createLine(mapToScene(event->pos()));
}
else if (strText == "矩形")
{
scene->createRect(mapToScene(event->pos()));
}
else
{
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QPixmap pixmap;
dataStream >> pixmap;
scene->createPixmap(mapToScene(event->pos()), pixmap);
}
event->acceptProposedAction();
}
QGraphicsView::dropEvent(event);
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QStringList list1;
list1 <<"直线" <<"矩形";
MyListWidget *listWidget1 = new MyListWidget(this);
listWidget1->addItems(list1);
listWidget1->setIconSize(QSize(200,200));
listWidget1->setGeometry(100,150,300,200);
listWidget1->setDragEnabled(true);
m_scene = new MyGraphicsScene();
m_scene->setSceneRect(QRectF(-300,-200,600,400));
m_view = new MyGraphicsView(this);
m_view->setScene(m_scene);
m_view->setGeometry(500,100,400,600);
m_view->setAcceptDrops(true);
}
一般的应用:QListWidget控件发送拖拽,Qgraphicview接收。
发送
#ifndef MYLISTWIDGET_H
#define MYLISTWIDGET_H
#include <QObject>
#include <QListWidget>
class MyListWidget:public QListWidget
{
Q_OBJECT
public:
MyListWidget(QWidget *parent=0);
~MyListWidget();
protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
QPoint m_dragPosition; // 拖放起点
QListWidgetItem *m_dragItem; // 被拖放的item
public:
QStringList m_strList;
};
#endif // MYLISTWIDGET_H
#include "mylistwidget.h"
#include <QMouseEvent>
#include <QListWidgetItem>
#include <QDrag>
#include <QApplication>
#include <QMimeData>
#include <QPainter>
#include <QPixmap>
MyListWidget::MyListWidget(QWidget *parent):
QListWidget(parent)
{
}
MyListWidget::~MyListWidget(){
}
void MyListWidget::mouseMoveEvent(QMouseEvent *event)
{
if (!(event->buttons()&Qt::LeftButton))
return;
if ((event->pos() - m_dragPosition).manhattanLength() < QApplication::startDragDistance())
return;
if (!m_dragItem)
return;
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
QString strtext = currentItem()->text();
if (strtext.isEmpty())
{
int row = currentRow() - 2;
QByteArray encodedData;
QDir dir1;
QString strdir = dir1.currentPath();
QString strfile = strdir + "/svg/" + m_strList[row];
QDataStream stream(&encodedData, QIODevice::WriteOnly);
{
QPixmap pixmap(strfile);
stream << pixmap;
}
mimeData->setData("draglist", encodedData);
}
else
{
mimeData->setData("draglist", strtext.toUtf8());
}
drag->setMimeData(mimeData);
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
void MyListWidget::mousePressEvent(QMouseEvent *event){
m_dragPosition=event->pos();
m_dragItem=this->itemAt(event->pos());
//保持父类继承下来的按键行为
QListWidget::mousePressEvent(event);
}
接收
#ifndef MYGRAPHICSSCENE_H
#define MYGRAPHICSSCENE_H
#include <QObject>
#include <QGraphicsView>
class MyGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
MyGraphicsScene(QWidget *parent=0);
~MyGraphicsScene();
void createRect(const QPointF &pt);
void createLine(const QPointF &pt);
void createPixmap(const QPointF &pt, const QPixmap &pixmap);
private:
QGraphicsScene *m_scene;
};
#endif // MYGRAPHICSSCENE_H
#include "mygraphicsscene.h"
#include <QDebug>
#include <QMimeData>
#include <QGraphicsSceneDragDropEvent>
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QPen>
#include "mygraphicslineitem.h"
#include "mygraphicsrectitem.h"
#if _MSC_VER >=1600
#pragma execution_character_set("utf-8")
#endif
MyGraphicsScene::MyGraphicsScene(QWidget *parent):
QGraphicsScene(parent)
{
}
MyGraphicsScene::~MyGraphicsScene()
{
}
void MyGraphicsScene::createRect(const QPointF &pt)
{
//MyGraphicsRectItem *item=new MyGraphicsRectItem;
QGraphicsRectItem *item = new QGraphicsRectItem();
item->setBrush(Qt::red);
item->setRect(0,0,20,30);
item->setPos(pt);
qDebug() << "createRect pos:" << pt.x() << pt.y();
// item->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
addItem(item);
}
void MyGraphicsScene::createLine(const QPointF &pt)
{
MyGraphicsLineItem *item=new MyGraphicsLineItem;
item->setPos(pt);
item->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
addItem(item);
}
void MyGraphicsScene::createPixmap(const QPointF &pt, const QPixmap &pixmap)
{
QGraphicsPixmapItem *item = new QGraphicsPixmapItem();
item->setPixmap(pixmap);
item->setPos(pt);
qDebug() << "createRect pos:" << pt.x() << pt.y();
// item->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
addItem(item);
}
#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H
#include <QObject>
#include <QGraphicsView>
class MyGraphicsView : public QGraphicsView
{
public:
MyGraphicsView(QWidget *parent=0);
~MyGraphicsView();
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event) ;
void dropEvent(QDropEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event) ;
public:
bool m_blinedraw{false};
private:
QPoint startpoint;
QPoint finishpoint;
};
#endif // MYGRAPHICSVIEW_H
#include "mygraphicsview.h"
#include "mygraphicsscene.h"
#include <QDragEnterEvent>
#include <QMimeData>
#include <QDebug>
#include <QMouseEvent>
#include <QPoint>
#include <QGraphicsLineItem>
#if _MSC_VER >=1600
#pragma execution_character_set("utf-8")
#endif
MyGraphicsView::MyGraphicsView(QWidget *parent):
QGraphicsView(parent)
{
startpoint.setX(0);
startpoint.setY(0);
finishpoint.setX(0);
finishpoint.setY(0);
}
MyGraphicsView::~MyGraphicsView()
{
}
void MyGraphicsView::dragEnterEvent(QDragEnterEvent *event)
{
if(event->mimeData()->hasFormat("text/plain")){
event->acceptProposedAction();
qDebug() << "view dragEnterEvent";
}
QGraphicsView::dragEnterEvent(event);
}
void MyGraphicsView::dragMoveEvent(QDragMoveEvent *event)
{
qDebug() << "view dragMoveEvent";
event->acceptProposedAction();
}
void MyGraphicsView::dropEvent(QDropEvent *event)
{
qDebug() << "view dropevent";
if (event->mimeData()->hasFormat("draglist"))
{
QByteArray itemData = event->mimeData()->data("draglist");
QString strText = itemData;
MyGraphicsScene *scene=(MyGraphicsScene*)this->scene();
QPoint po = event->pos();
qDebug() << "dropevent pos:"<< po.x() << po.y() ;
if (strText == "直线")
{
scene->createLine(mapToScene(event->pos()));
}
else if (strText == "矩形")
{
scene->createRect(mapToScene(event->pos()));
}
else
{
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QPixmap pixmap;
dataStream >> pixmap;
scene->createPixmap(mapToScene(event->pos()), pixmap);
}
event->acceptProposedAction();
}
QGraphicsView::dropEvent(event);
}
void MyGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
QGraphicsView::mouseMoveEvent(event);
int a = 1;
}
void MyGraphicsView::mousePressEvent(QMouseEvent *event)
{
if (event->button()==Qt::LeftButton && m_blinedraw)
{
QPoint viewpos = event->pos();
QPointF scenepos = mapToScene(viewpos);
QGraphicsItem *item=NULL;
item = scene()->itemAt(scenepos,transform());
if (item != nullptr) //有绘图项
{
startpoint = viewpos;
}
}
QGraphicsView::mousePressEvent(event);
int a = 1;
}
void MyGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button()==Qt::LeftButton && m_blinedraw)
{
QPoint viewpos = event->pos();
QPointF scenepos = mapToScene(viewpos);
QGraphicsItem *item=NULL;
item = scene()->itemAt(scenepos,transform());
if (item != nullptr && !(startpoint.x() == 0 && startpoint.y() == 0) ) //有绘图项
{
finishpoint = viewpos;
QLineF line(mapToScene(startpoint),scenepos);
QGraphicsLineItem *lineitem = new QGraphicsLineItem(line);
scene()->addItem(lineitem);
startpoint.setX(0);
startpoint.setY(0);
finishpoint.setX(0);
finishpoint.setY(0);
}
}
QGraphicsView::mouseReleaseEvent(event);
}
#ifndef MYGRAPHICSLINEITEM_H
#define MYGRAPHICSLINEITEM_H
#include <QGraphicsItem>
class MyGraphicsLineItem : public QGraphicsItem
{
public:
MyGraphicsLineItem();
~MyGraphicsLineItem();
QRectF boundingRect()const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};
#endif // MYGRAPHICSLINEITEM_H
#include "mygraphicslineitem.h"
#include <QPainter>
#include <QBrush>
MyGraphicsLineItem::MyGraphicsLineItem()
{
}
MyGraphicsLineItem::~MyGraphicsLineItem()
{
}
QRectF MyGraphicsLineItem::boundingRect() const
{
qreal penWidth=1;
return QRectF(0-penWidth/2,0-penWidth/2,4+penWidth,80+penWidth);
}
void MyGraphicsLineItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
painter->setBrush(Qt::red);
painter->drawRect(0,0,4,80);
}
#ifndef MYGRAPHICSRECTITEM_H
#define MYGRAPHICSRECTITEM_H
#include <QGraphicsItem>
class MyGraphicsRectItem : public QGraphicsItem
{
public:
MyGraphicsRectItem();
~MyGraphicsRectItem();
QRectF boundingRect()const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};
#endif // MYGRAPHICSRECTITEM_H
#include "mygraphicsrectitem.h"
#include <QPainter>
#include <QDebug>
#include <QBrush>
MyGraphicsRectItem::MyGraphicsRectItem()
{
}
MyGraphicsRectItem::~MyGraphicsRectItem()
{
}
QRectF MyGraphicsRectItem::boundingRect() const
{
qreal penWidth=1;
return QRectF(0-penWidth/2,0-penWidth/2,18+penWidth,56+penWidth);
}
void MyGraphicsRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option)
Q_UNUSED(widget)
painter->setBrush(Qt::red);
painter->drawRect(0,0,18,56);
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtSvg>
namespace Ui {
class Widget;
}
class MyGraphicsScene;
class MyGraphicsView;
class MyListWidget;
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
MyGraphicsScene * m_scene;
MyGraphicsView *m_view;
MyListWidget *listWidget1;
private:
Ui::Widget *ui;
protected:
void paintEvent(QPaintEvent *event);
QSvgRenderer* svgRender;
public slots:
void readbuttonslot();
void writebuttonslot();
void Linebuttonslot();
void Allreadbuttonslot();
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include "mylistwidget.h"
#include "mygraphicsscene.h"
#include <QDebug>
#include <QGraphicsItem>
#include <QList>
#include <mygraphicsview.h>
#include "mysvgwidget.h"
#include <QPushButton>
#if _MSC_VER >=1600
#pragma execution_character_set("utf-8")
#endif
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QStringList list1, list2;
list1 <<"直线" <<"矩形";
list2 <<"阿童木" <<"皮卡丘" <<"卡卡西" <<"奈落"<<"一休" << "黑猫警长" <<"兔八哥"<<"三毛"<<"舒克"<<"贝塔";;
listWidget1 = new MyListWidget(this);
listWidget1->addItems(list1);
listWidget1->setIconSize(QSize(32,32));
listWidget1->setGeometry(100,100,500,300);
listWidget1->setDragEnabled(true);
m_scene = new MyGraphicsScene();
m_scene->setSceneRect(QRectF(-300,-200,600,400));
m_view = new MyGraphicsView(this);
m_view->setScene(m_scene);
m_view->setGeometry(500,100,400,600);
m_view->setAcceptDrops(true);
// m_view->show();
QString strPath = "arrow.svg";
svgRender = new QSvgRenderer(this);
bool ret = svgRender->load(QString("G:/opencode/qt/msvc/test/drag/arrow.svg"));
int a = 1;
MySvgWidget *psvgwidget;
psvgwidget = new MySvgWidget(this);
psvgwidget->setGeometry(200,0,200,200);
psvgwidget->show();
psvgwidget->load(QString("G:/opencode/qt/msvc/test/drag/arrow.svg"));
QPushButton *pReadbutton = new QPushButton(tr("加载svg"),this);
pReadbutton->setGeometry(10,height()-50,60,40);
connect(pReadbutton,SIGNAL(clicked()),this,SLOT(readbuttonslot()));
QPushButton *pWritebutton = new QPushButton(tr("保存svg"),this);
pWritebutton->setGeometry(100,height()-50,60,40);
connect(pWritebutton,SIGNAL(clicked()),this,SLOT(writebuttonslot()));
QPushButton *pLinebutton = new QPushButton(tr("连线"),this);
pLinebutton->setGeometry(200,height()-50,60,40);
connect(pLinebutton,SIGNAL(clicked()),this,SLOT(Linebuttonslot()));
QPushButton *pAllReadbutton = new QPushButton(tr("一键加载svg"), this);
pAllReadbutton->setGeometry(280, height() - 50, 60, 40);
connect(pAllReadbutton, SIGNAL(clicked()), this, SLOT(Allreadbuttonslot()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter p(this);
svgRender->render(&p,QRectF(0,0,100,100));
}
void Widget::readbuttonslot()
{
QString filePath = QFileDialog::getOpenFileName(0, "打开文件", ".", "SVG(*.svg)");
if(filePath.isEmpty())
{
return;
}
QSvgRenderer *renderer = new QSvgRenderer(filePath);
QGraphicsSvgItem *blackSvgItem = new QGraphicsSvgItem();
blackSvgItem->setSharedRenderer(renderer);
m_scene->addItem(blackSvgItem);
blackSvgItem->setFlags (QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
}
void Widget::writebuttonslot()
{
QString filePath = QFileDialog::getSaveFileName(0, "保存文件", ".", "SVG(*.svg)");
if(filePath.isEmpty())
{
return;
}
QSvgGenerator svgGenerator;
svgGenerator.setFileName(filePath);
svgGenerator.setSize(QSize(rect().width(), rect().height()));
svgGenerator.setViewBox(rect()); svgGenerator.setTitle("测试QSvgGenerator");
svgGenerator.setDescription("另存为绘制测试");
QPainter painter;
painter.begin(&svgGenerator);
painter.setPen(Qt::red);
painter.drawLine(QPointF(20,20),QPointF(100,100));
painter.drawText(rect(), "测试Svg");
QPixmap pixmap = this->grab(QRect(0, 0, 1000, 800));
painter.drawPixmap(10,10,pixmap);
painter.end();
}
void Widget::Linebuttonslot()
{
if(m_view)
{
m_view->m_blinedraw = true;
}
}
void Widget::Allreadbuttonslot()
{
listWidget1->m_strList.clear();
QDir dir1;
QString strdir = dir1.currentPath();
strdir += "/svg";
QDir dir(strdir);
listWidget1->m_strList = dir.entryList(QDir::Files);
int num = listWidget1->m_strList.size();
QString strfile;
for (int i = 0; i < num; ++i)
{
strfile = strdir + "/" +listWidget1->m_strList[i];
QListWidgetItem *item = new QListWidgetItem(QIcon(strfile),"");
listWidget1->addItem(item);
}
}