当前位置: 首页 > news >正文

Qt官方案例知识点总结(拖放操作——Drag And Drop Robot )

--------------------------------------------------------------------------------------------------------------------------------

QPixmap轮廓剪裁 

 去掉Pixmap的外围部分,如下:

QPixmap pixmap("./img");
//调用createHeuristicMask(),再调用setMask
pixmap.setMask(pixmap.createHeuristicMask());

效果对比:

 ——》

可以看到以图像内轮廓为边界线,无关的白色区域被抹去了

---------------------------------------------------------------------------------------------------------------------------------

QGraphicsItem中开启拖动QDrag

重写QGraphicsItem的鼠标移动事件,在移动事件中开启拖动

void ColorItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) {//判断拖动距离,使用qt推荐的距离QApplication::startDragDistance()if (QLineF(event -> screenPos(), event -> buttonDownScreenPos(Qt::LeftButton)).length() < QApplication::startDragDistance()) {return;}//创建拖动对象QDrag * drag = new QDrag(event -> widget());//创建数据对象,并设置给本次拖动,这样本次拖动就有数据了QMimeData * mime = new QMimeData;drag -> setMimeData(mime);QImage image(":/images/head.png");mime -> setImageData(image);//可以设置图像数据mime -> setColorData(color);//颜色数据mime -> setText(QString("#%1%2%3").arg(color.red(), 2, 16, QLatin1Char('0')).arg(color.green(), 2, 16, QLatin1Char('0')).arg(color.blue(), 2, 16, QLatin1Char('0')));//字符串数据QPixmap pixmap(34, 34);pixmap.fill(Qt::white);drag -> setPixmap(pixmap);//设置拖动过程中在鼠标处显示的图片drag->setHotSpot(QPoint(15, 20));//设置鼠标在图片里的位置偏移drag -> exec();//开启本次拖动
}

qt推荐的拖动距离阈值:QApplication::startDragDistance() ,超过这个距离才启用拖动

创建的拖动对象(QDrag * drag)可以指定父对象也可以不指定,他会在这次拖动结束时自动释放,无论这次拖动有没有被drop接收 

创建的数据对象QMimeData在设置给拖动对象后也不用管他的释放(drag -> setMimeData(mime);),会跟着拖动对象一起释放

同时还可以设置鼠标在拖动的过程下面跟随着图片drag -> setPixmap(pixmap)

拖动执行函数

Qt::DropAction QDrag::exec(Qt::DropActions supportedActions = Qt::MoveAction)
Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defaultDropAction)

常用的行为就是复制、移动、空操作 

这是一个阻塞函数,

拖动结束后可以获取到返回值, 来获取到本次拖动最终执行了什么行为

supportedActions可以指定本次拖动支持的行为

defaultDropAction可以指定本次拖动默认的行为

---------------------------------------------------------------------------------------------------------------------------------

QMimeData携带自定义数据

其中QMimeData可以设置自定义的数据,需要继承重写或者调用setData方法  

  • 使用setData方法

他的第一个参数是一个字符串,指定数据的类型,可以自己定义

二个参数QByteArray,即要传输的数据

比如数据是1个结构体

结构体需要提供转成QByteArray的方法从QByteArray转到结构体的方法

// 自定义数据结构
struct Person {QString name;int age;// 序列化到 QByteArrayQByteArray serialize() const {QByteArray data;QDataStream stream(&data, QIODevice::WriteOnly);stream << name << age;return data;}// 从 QByteArray 反序列化static Person deserialize(const QByteArray &data) {QDataStream stream(data);QString name;int age;stream >> name >> age;return {name, age};}
};

创建自定义数据 ,指定类型的字符串可以自己随便写

// 创建自定义数据
Person person{"Alice", 30};// 序列化并设置到 QMimeData
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/x-custom-person", person.serialize());

接收方解析自定义数据

// 获取 QMimeData(例如从拖放事件)
const QMimeData *mimeData = event->mimeData();// 检查是否存在自定义数据
if (mimeData->hasFormat("application/x-custom-person")) {// 提取数据并反序列化QByteArray data = mimeData->data("application/x-custom-person");Person person = Person::deserialize(data);qDebug() << "Received person:" << person.name << person.age;
}
  • 最小子类化QMimeData

即不重写相关虚函数,直接将数据作为其子类的成员变量,如下

比如把Person传出去

//自定义数据
struct Person{QString name="11"  ;int age=15;
};//子类化QMimeData,将自定义的类型作为其成员变量
class PersonMimeData: public QMimeData
{
public:Person person;//...还可以携带N多数据成员
};

创建自定义的MimeData

//创建自定义的MimeData,并初始化里面自定义的数据,然后设置给QDrag对象
QDrag * drag = new QDrag(event -> widget());
PersonMimeData * mime = new PersonMimeData;
mime -> person = {"May", 18};
drag -> setMimeData(mime);

接受方解析收到的数据

//从事件中获取mimedata(例如拖放事件),并强转成对应的类型
PersonMimeData * data = (PersonMimeData * ) event -> mimeData();
//取出内部携带的数据
qDebug() << data -> person.name << "   " << data -> person.age;

---------------------------------------------------------------------------------------------------------------------------------

QGraphicsItem中的drop拖放

  • 需要QGraphicsItem接受拖放
setAcceptDrops(true);
  • 需要重写dragEnterEvent事件,拖动进入事件

可对拖动携带数据做一些判断,判断是否有想要的数据

需要接受拖动,则需要显示的调用 event->setAccepted(true),否则后面的拖放事件会收不到数据

void CustomItem::dragEnterEvent(QGraphicsSceneDragDropEvent * event) {//可以对拖过来的数据进行一些判断,有没有想要的数据if (event -> mimeData() -> hasColor()) {event -> setAccepted(true); //然后要接受这次拖放,否则后面drop事件无法收到拖放//同时可以改变下item的样式,isDragging = true; //自己定义的标志变量,标记拖动进入了update();} else {event -> setAccepted(false); //否则拒绝这次拖放}
}
  • 需要重写拖放事件

主要就是获取本次拖放的mimeData

设置本次拖放最后采用的行为

void CustomItem::dropEvent(QGraphicsSceneDragDropEvent *event)
{isDragging = false;update();auto data=event->mimeData();//取mimeData里的数据//data->text();...event->setDropAction(Qt::CopyAction);//还可以设置本次拖放最后使用的行为,QDrag的exec函数的返回值就会变成这里设置的
}
  • 需要重写拖动离开事件

主要就是设置标记变量,表示拖动离开了

同时刷新下样式

void CustomItem::dragLeaveEvent(QGraphicsSceneDragDropEvent * event) {Q_UNUSED(event);isDragging = false;update();
}

---------------------------------------------------------------------------------------------------------------------------------

并行动画组QParallelAnimationGroup

可以在动画组里添加多个动画,这些动画可以同时进行

QParallelAnimationGroup * animation = new QParallelAnimationGroup(this);QPropertyAnimation * a1 = new QPropertyAnimation(target1, "rotation");
a1 -> setStartValue(5);
a1 -> setEndValue(-20);
animation -> addAnimation(a1);QPropertyAnimation * a2 = new QPropertyAnimation(target2, "rotation");
a2 -> setStartValue(15);
a2 -> setEndValue(-30);
animation -> addAnimation(a2);
//.....可以添加多个动画,这些动画可以同时执行animation -> setLoopCount(-1); //无限循环
animation -> start(); //并行动画组开启,多个动画同时运行

其中animation -> setLoopCount(-1); 参数设置为-1,可让动画无限循环

---------------------------------------------------------------------------------------------------------------------------------

正弦动画曲线

动画曲线类型QEasingCurve::SineCurve,正弦曲线

可以使动画1个执行周期内产生一来一回的效果,来和回是完全相反的两个动画,如下

其他曲线没有来回的效果

比如QEasingCurve::OutQuad,如下

相关文章:

  • 【Linux 网络】网络工具ifconfig和iproute/iproute2工具详解
  • java网络原理5
  • Linux 基础IO(上)--文件与文件描述符fd
  • python将字符串转成二进制数组
  • JVM快速入门
  • scGPT方法解读
  • (即插即用模块-特征处理部分) 四十五、(2024 TGRS) SFF 浅层特征融合模块
  • WebRtc09:网络基础P2P/STUN/TURN/ICE
  • [实战] Petalinux驱动开发以及代码框架解读
  • IBM WebSphere Application Server 7.0/8.5.5证书过期问题处理
  • firecrawl的docker安装和api调用
  • 【python】-基础语法3
  • flutter开发音乐APP(简单的音乐播放demo)
  • Android Compose 无网络状态处理全指南:从基础到高级实践
  • 家庭服务器IPV6搭建无限邮箱系统指南
  • 米壳AI:跨境电商图片翻译的“隐形革命”:当AI技术遇上全球化生意
  • 每日算法-250430
  • 高性能架构设计-分库分表
  • 2025上海车展 | 移远通信推出自研NG-eCall QuecOpen方案,助力汽车安全新标准加速落地
  • AVPro Video加载视频文件并播放,可指定视频文件的位置、路径等参数
  • 中国代表:美“对等关税”和歧视性补贴政策严重破坏世贸规则
  • 媒体:酒店、民宿临时毁约涨价,怎么管?
  • 日菲同意扩大安全合作,外交部:反对任何在本地区拉帮结派的做法
  • 特朗普加征关税冲击波:美国零售、汽车、航空、科技企业纷纷预警业绩波动
  • 国台办:相关优化离境退税政策适用于来大陆的台湾同胞
  • 广东省副省长刘红兵任湖南省委常委、宣传部部长