Qt实现拖动单个控件移动的示例代码

目录
  • 1.设置窗口拖拽属性
  • 2.创建初始控件
  • 3.选中控件进行拖动
    • 3.1响应mousePressEvent事件
    • 3.2判断控件拖动
    • 3.3事件处理
    • 3.4结束拖动

做惯了静态图,今天来搞一搞动态图吧,首先来个最基础的功能:如果让一个控件拖动起来。

展示效果:

按照以往简单的做法,使用mouseMoveEvent、mousePressEvent、mouseReleaseEvent也是可以实现的。这是最基础的移动做法。

今天,不使用那种简单的做法,采用Qt一种特有的拖动方法来实现!

使用QDropEvent实现拖拽事件。

实现控件拖拽的流程,如下:

1:创建一个控件,这里使用QLabel控件。

2:选中需要拖拽的控件

3:重写拖拽事件。

根据上述操作流程,来实现一个控件的拖拽吧!

1.设置窗口拖拽属性

在Qt中,默认是不响应拖拽消息的,这跟mouseMoveEvent消息默认不响应是一样的,必须明确调用,告诉窗口,需要响应此消息。

this->setAcceptDrops(true);

2.创建初始控件

创建一个初始控件,用于初始拖动使用。

QLabel *labIcon = new QLabel(this);
labIcon->setText("");
labIcon->setPixmap(QPixmap(":/QDragSingleLabel/image/boat.png"));
labIcon->move(10, 10);
labIcon->show();
labIcon->setAttribute(Qt::WA_DeleteOnClose);

偷懒起见,对QLabel控件设置了窗口关闭销毁的功能,很是方便。

3.选中控件进行拖动

鼠标在控件上按下,开始做拖动操作;当鼠标抬起时,不进行拖动操作。

3.1响应mousePressEvent事件

需要知道鼠标是否点击到控件上

这里需要特殊注意的是:QLabel是一个静态控件,正常情况下是不会响应鼠标选中效果的。

此时,需要响应QWidget鼠标按下的事件,将鼠标点击的点转换成是否选中QLabel控件,侧面实现数据点击控件效果。

QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
if(!child)
{
    //不是QLabel控件,不进行处理
    return;
}

QWidget::childAt(const QPoint& p)const;说明:返回窗口小部件自身坐标系统中p点处的可见子窗口小部件。

查询到有效QLabel指针后,创建一个可存储在剪贴板中的信息,通过拖放机制进行传输的。这里采用:QMimeData类实现。

优势该类可以确保信息在应用程序之间安全传输,并且可以在相同的应用程序内复制。

创建该类并将QLabel中的数据传入到类中,用于做拖拽使用。

QMimeData *mimeData = new QMimeData;
mimeData->setData(qsEnum, itemData);

设置数据。

qsEnum:类型:QString。

在这里可以设置任意字符串,只要保证在拖拽消息时用的一个字符串就可以。为了方便统一,将该字符串做了统一设置。

const QString qsEnum = "zhongGuoHaoGongMin";//自定义数据类型

itemData:类型:QByteArray。

对QMimeData传入的数据,这里存放了QLabel的图片以及显示位置。

QPixmap pixmap = *child->pixmap();
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << pixmap << QPoint(event->pos() - child->pos());

上述内容准备就绪后,创建拖拽类,用于数据拖拽。

QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(pixmap);
drag->setHotSpot(event->pos() - child->pos());

将数据传递给拖动对象,设置将在操作期间与光标一起显示的像素图,并定义一个热点的位置,该热点将像素图的位置置于光标之下。

绘制拖动的位置,这里采用了QPainter绘制机制

QPixmap tempPixmap = pixmap;
QPainter painter;
painter.begin(&tempPixmap);
painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127));
painter.end();

child->setPixmap(tempPixmap);

开始拖动操作,调用QDrag::exec();

3.2判断控件拖动

目前只有一个控件可以拖动,那么,当创建多个拖动控件时,该如何判断要拖动哪个呢?

这时候,在创建QMimeData传入的自定义数据类型就起到作用了。

当数据类型是qsEnum时,进行判断,如果不是,不进行判断。

if (event->mimeData()->hasFormat(qsEnum))
{
    //进行判断
}
else
{
    event->ingnore(); //忽略判断
}

事件:dragEnterEvent、dragMoveEvent、dropEvent都需要这样判断。

3.3事件处理

当前是匹配的自定义数据类型时,并且是该资源是,接受拖动进入事件,并设置当前为拖动事件。

if (event->source() == this)
{
	event->setDropAction(Qt::MoveAction);
	event->accept();
}

否则设置执行操作并接收该事件

else
{
    event->acceptProposedAction();
}

3.4结束拖动

结束拖动,响应事件:virtual void dropEvent(QDropEvent *event)override;

除了处理操作3中的事件处理,还需要当鼠标结束操作时,需要在新的位置上重新创建QLabel控件。并将鼠标按下时创建的QMimeData数据获取出来,显示到新创建的QLabel控件上。

QByteArray itemData = event->mimeData()->data(qsEnum);
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QPixmap pixmap;
QPoint offset;
dataStream >> pixmap >> offset;

QLabel *newIcon = new QLabel(this);
newIcon->setPixmap(pixmap);
newIcon->move(event->pos() - offset);
newIcon->show();
newIcon->setAttribute(Qt::WA_DeleteOnClose);

dropEvent消息是什么时候被触发呢?

当鼠标左键弹起时,说明结束了控件拖动事件,需要调用dropEvent并重新创建控件,显示新位置。

Qt::DropAction n = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
if (n == Qt::MoveAction)
{
    //结束操作
    child->close();
}
else
{
    //继续拖动控件,实时显示新位置
    child->show();
    child->setPixmap(pixmap);
}

到此这篇关于Qt实现拖动单个控件移动的示例代码的文章就介绍到这了,更多相关Qt拖动控件移动内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Qt自定义控件实现仪表盘

    目录 1.预览图 2. 代码 头文件 源文件 3. 用法 1.预览图 2. 代码 头文件 #ifndef MOTORMETER_H #define MOTORMETER_H #include <QWidget> #include <QDebug> #include <QtMath> #include <QDialog> #include <QPainter> #include <QPaintEvent> #include <QP

  • Qt编写显示密码强度的控件

    本文实例为大家分享了Qt编写显示密码强度控件的具体代码,供大家参考,具体内容如下 代码: #ifndef WIDGET_H #define WIDGET_H   #include <QWidget> #include <QRegularExpression> #include <QTimer>   class PasswordStrengthCheck : public QWidget {     Q_OBJECT   public:     PasswordStren

  • Qt简单实现密码器控件

    本文实例为大家分享了Qt自定义一个密码器控件的简单实现代码,供大家参考,具体内容如下 实现构思: 密码器的功能可以看成是计算器和登陆界面的组合,所以在实现功能的过程中借鉴了大神的计算器的实现代码和登陆界面实现的代码. 实现的效果: 关于密码器控件的不足: 窗口的标题栏不够漂亮,但是由于对时间长度和任务进度的权衡,下次一定进行重绘. 代码思路: 由于我司不用样式表,所以背景由贴图函数完成.在widget中添加按钮控件和文本编辑控件.使用布局函数进行布局,在加上一些简单的逻辑处理功能即可. 首先创建

  • Qt基于QScrollArea实现界面嵌套移动

    在实际的应用场景中,经常会出现软件界面战场图大于实际窗体大小,利用QScrollArea可以为widget窗体添加滚动条,可以实现小窗体利用滚动条显示大界面需求.实现如下: QT创建一个qWidget界面 在ui界面中利用QT自带的widget控件布局一个如下图所示的层叠关系,widget_2界面大小需大于widget大小 界面布局好后,将widget_2提升为类,提升之前需为工程新添加一个设计界面类,添加完之后,将widget_2提升为类类名和前面新添加的设计界面类名一致 源码实现如下 pat

  • Qt实现图片移动实例(图文教程)

    这学期实训的时候用MFC做过一个飞机大战,很无聊的东西,一直想用Qt做一个,但是在学校的时候比较颓,回来看了一下. 首先需要解决的问题是图片的移动,怎么说飞机啊子弹啊都是动着的,图片当然要跑起来. 闲话休絮,首先用QtCreator新建一个QtGui程序,命名为PaintWidget,随便起的名字,实验么这不是. 会生成这三个文件,其中呢ui不用管,实验的图片移动需要用的是Event,不是信号槽,所以ui就不管了,放了那就是. 第一步要把图片画出来,参照<Qt学习之路的这段代码>,不难把图画出

  • Qt实现拖动单个控件移动的示例代码

    目录 1.设置窗口拖拽属性 2.创建初始控件 3.选中控件进行拖动 3.1响应mousePressEvent事件 3.2判断控件拖动 3.3事件处理 3.4结束拖动 做惯了静态图,今天来搞一搞动态图吧,首先来个最基础的功能:如果让一个控件拖动起来. 展示效果: 按照以往简单的做法,使用mouseMoveEvent.mousePressEvent.mouseReleaseEvent也是可以实现的.这是最基础的移动做法. 今天,不使用那种简单的做法,采用Qt一种特有的拖动方法来实现! 使用QDrop

  • Android官方的侧滑控件DrawerLayout的示例代码

    导语 侧滑控件,以前大家用的可能是三方的SlidingMenu控件,最近在看谷歌源码项目,意外的看到一个 DrawerLayout 控件.上网一查,原来这个控件是官方给我们提供的一个侧滑菜单控件.既然谷歌已经提供了一个侧滑控件,我们又何必去用一个三方的SlidingMenu控件来实现相同的效果.于是,我决定自己手敲一个Demo来实现看看. 1.DrawerLayout效果图 2.DrawerLayout 的介绍 DrawerLayout的官方文档介绍链接:http://androiddoc.qi

  • Android更多条目收缩展开控件ExpandView的示例代码

    在Android开发中,我们经常使用列表控件,而有时候列表控件条目中又会是多条目数据,这时候,我们无法确定每个条目的数据多少,而为了美观,我们就希望条目统一高度,多数据的条目能够进行折叠.展开.今天,就为大家介绍一个这样的自定义控件 ExpandView. 效果演示图 演示图 Android Studio集成方式 dependencies{ compile 'com.wkp:ExpandView:1.0.4' //Android Studio3.0+可用以下方式 //implementation

  • iOS中各种UI控件属性设置示例代码

    //视图已经加载完了,可以进行ui的添加了 - (void)viewDidLoad { [superviewDidLoad]; // Do any additional setup after loading the view. //初始化UILabel注意指定该对象的位置及大小 UILabel *lb = [[UILabelalloc]initWithFrame:CGRectMake(0,20,300,200)]; //设置文字 lb.text =@"label测试我在学习中学些ui stor

  • Android中SeekBar拖动条控件使用方法详解

    SeekBar拖动条控件使用方法,具体内容如下 一.简介 1.  二.SeekBar拖动条控件使用方法 1.创建SeekBar控件 <SeekBar android:id="@+id/SeekBar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:progress="30" /> 2.添加setOn

  • 基于SurfaceView实现可拖动视频控件

    本文实例为大家分享了基于SurfaceView的可拖动视频控件,供大家参考,具体内容如下 public class DragSurfaceView extends SurfaceView implements View.OnTouchListener { protected int screenWidth; protected int screenHeight; protected int lastX; protected int lastY; private int oriLeft; priv

  • Android开发之拖动条/滑动条控件、星级评分控件功能的实例代码

    ProgressBar有2个子控件: SeekBar   拖动条控件 RatingBar   星级评分控件 1.拖动条控件 <SeekBar android:layout_width="300dp" android:layout_height="wrap_content" android:id="@+id/seekBar" android:min="0" android:max="100" andro

  • Android开发自定义双向SeekBar拖动条控件

    目录 目标:双向拖动的自定义View 实现步骤 自定义属性获取 确定自定义view尺寸 绘制相关的内容部分 滑动事件处理 目标:双向拖动的自定义View 国际惯例先预览后实现 我们要实现的就是一个段位样式的拖动条,用来做筛选条件用的,细心的朋友可能会发现微信设置里面有个一个通用字体的设置,拖动然后改变字体大小; 这个相对比微信那个的自定义view算是一个扩展,因为我们是双向滑动,这个多考虑的一点就是手指拖动的是哪一个滑动块! 我们先看下GIF预览,然后我们今天就一步步实现这个小玩意… 实现步骤

  • PyQt5中向单元格添加控件的方法示例

    1.简介 pyqt 列表 单元格中 不仅可以添加数据,还可以添加控件. 我们尝试添加下拉列表.一个按钮试试. setItem:将文本放到单元格中 setCellWidget:将控件放到单元格中 setStyleSheet:设置控件的样式(Qt StyleSheet) 2.功能实现 # -*- coding: utf-8 -*- ''' [简介] PyQT5中 单元格里面放控件 ''' import sys from PyQt5.QtWidgets import (QWidget, QTableW

  • 简单仿写Android控件SlidingMenu的实例代码

    SlidingMenu (侧滑菜单形式)在android开发过程中,经常用到,这次我们通过一个简单案例来仿写SlidingMenu 的大体功能,下面 是主要实现的代码: java代码:(重写onTouchEvent方法 处理侧滑菜单处的事件分发机制) public class SlidingMenu extends ViewGroup implements OnClickListener { private View menu; private View main; private int me

随机推荐