(1)先给出 Qt 里对拖放事件的枚举定义 :
++再给出这些拖放类的继承关系 :
(2) 先给出 QDrag 类,定义于 qdrag . h 头文件 :
#ifndef QDRAG_H
#define QDRAG_H
#include <QtGui/qtguiglobal.h>
#include <QtCore/qobject.h>
QT_REQUIRE_CONFIG(draganddrop);
QT_BEGIN_NAMESPACE
class QMimeData;
class QDragPrivate;
class QPixmap;
class QPoint;
class QDragManager;
/*
The QDrag class provides support for MIME-based drag and drop data transfer.
Detailed Description :
拖放操作是一种直观的用户方式,用于在应用程序中复制或移动数据,
并且在许多桌面环境中被用作在不同应用程序之间复制数据的机制。
Qt中的拖放支持主要围绕QDrag类展开,该类处理了拖放操作的大部分细节。。
通过拖放操作要传输的数据包含在QMimeData对象中。这通过以下方式在setMimeData()函数中指定:
QDrag * drag = new QDrag(this);
QMimeData * mimeData = new QMimeData;
mimeData->setText(commentEdit->toPlainText());
drag->setMimeData(mimeData);
请注意,`setMimeData()`函数将`QMimeData`对象的拥有权赋予`QDrag`对象。
QDrag`必须在堆上通过一个父`QObject`来构造,以确保在拖放操作完成之后,Qt能够进行清理。
在拖动的过程中,可以使用位图来代表数据,并且会随着光标移动到目标放置位置。
这个位图通常显示一个图标,代表正在传输的数据的MIME类型,但任何位图都可以通过调用`setPixmap、函数来设置。
使用`setHotSpot()、函数,可以设置光标的热点位置,使其相对于位图的左上角。
下面的代码将位图定位,使得光标的热点指向其下边缘的中心位置: //class Qpoint { int xp; int yp; };
drag->setHotSpot( QPoint(drag->pixmap().width()/2, drag->pixmap().height()) );
注:在X11上,如果热点导致位图直接显示在光标下方,那么该位图可能跟不上鼠标移动的速度。
源和目标小部件可以通过`source()、和`target()、函数找到。
这些函数常用于确定拖放操作是否在同一小部件上开始并结束,以便实现特殊行为。
QDrag只处理拖放操作本身。何时开始拖放操作以及如何构建和使用QDrag对象,这些取决于开发者。
对于特定的控件,通常有必要重写mousePressEvent()函数以确定用户是否按下了鼠标按钮,
并重写 mouseMoveEvent()函数以检查是否需要 QDrag。
*/
class Q_GUI_EXPORT QDrag : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QDrag)
private:
friend class QDragManager;
Q_DISABLE_COPY(QDrag)
Q_SIGNALS:
//This signal is emitted when the action associated with the drag changes.
void actionChanged(Qt::DropAction action);
void targetChanged(QObject * newTarget);
//This signal is emitted when the target of the drag and drop operation changes,
// with newTarget the new target.
public:
//Constructs a new drag object for the widget specified by dragSource.
explicit QDrag(QObject * dragSource);
~QDrag();
//取消由Qt发起的拖动操作。注意:此功能目前仅在Windows和X11上实现。
static void cancel();
//返回拖动对象的源 。这是拖放操作起始的控件。
QObject * source() const;
QObject * target() const;
//返回拖放操作的目标。这是将拖动对象放置的控件。
//Returns the default proposed drop action for this drag operation.
Qt::DropAction defaultAction () const;
Qt::DropActions supportedActions() const;
//Returns the set of possible drop actions for this drag operation.
//返回由拖动对象封装的MIME数据。
QMimeData * mimeData () const;
void setMimeData ( QMimeData * data );
//Sets the data to be sent to the given MIME data.
//Ownership of the data is transferred to the QDrag object.
//返回用于在拖放操作中表示数据的像素图。
QPixmap pixmap () const;
void setPixmap (const QPixmap & pixmap );
//Sets pixmap as the pixmap used to represent the data in a drag and drop operation.
//You can only set a pixmap before the drag is started.
//返回热点相对于光标左上角的位置。
QPoint hotSpot () const;
void setHotSpot (const QPoint & hotspot);
//Sets the position of the hot spot relative to the
// top-left corner of the pixmap used to the point specified by hotspot.
//设置热点相对于用于指定热点位置的像素图左上角的位置。
//注:在X11上,如果热点导致图像映射直接显示在光标下方,那么图像映射可能无法跟上鼠标移动的速度。
//Returns the drag cursor for the action. 返回的是位图。
QPixmap dragCursor(Qt::DropAction action ) const;
void setDragCursor(const QPixmap & cursor, Qt::DropAction action);
//Sets the drag cursor for the action.
//This allows you to override the default native cursors.
//To revert to using the native cursor for action, pass in a null QPixmap as cursor.
//为该操作设置拖曳光标。这允许您覆盖默认的本机光标。
//在作为光标传递的nullQPixmap 中,可以恢复使用本机光标。
//注意:在 IgnoreAction 上设置拖动光标可能并非所有平台都适用。
//X11和 macOs已经测试过可以正常工作。Windows不支持此功能。
//启动拖放操作,并在操作完成时返回表示所请求的拖放操作的结果。
//用户可选择的拖放操作在 supportedActions”中指定。
//默认建议的操作将在以下允许的操作中按以下顺序选取:移动、复制和链接
//在Linux和macOS上,拖放操作可能需要一些时间,但该功能并不会阻塞事件循环,
// 在操作进行时其他事件仍会被传递给应用程序。
//但在Windows上,操作期间会阻塞Qt事件循环。
Qt::DropAction exec(Qt::DropActions supportedActions = Qt::MoveAction);
Qt::DropAction exec(Qt::DropActions supportedActions,
Qt::DropAction defaultAction );
//启动拖放操作,并在操作完成时返回表示所请求的拖放操作的结果。
//用户可选择的拖放操作在 supportedActions~中指定。
//The defaultDropAction determines which action will be proposed when the
// user performs a drag without using modifier keys.
//默认的拖放操作确定当用户在不使用修饰键的情况下执行拖放时将提出哪种操作。
//注:在Linux和macOS上,拖放操作可能需要一些时间,但该功能并不会阻塞事件循环。
// 在操作进行时,其他事件仍会传递给应用程序。在Windows上,操作期间会阻塞Qt事件循环。
//然而,在Windows上使用QDrag:exec()会频繁调用processEvents()以保持GUI响应。
//如果在拖放操作进行期间调用了任何循环或操作,将会阻塞拖放操作。
}; //完结 class QDrag : public QObject
QT_END_NAMESPACE
#endif // QDRAG_H
(3)再给出最简单的 QDragLeaveEvent :
/*
The QDragLeaveEvent class provides an event that is sent to a
widget when a drag and drop action leaves it.
此事件总是由一个QDragEnterEvent和一系列QDragMoveEvents前置。
如果发送了QDropEvent,则不会发送此事件。
*/
class Q_GUI_EXPORT QDragLeaveEvent : public QEvent
{
Q_EVENT_DISABLE_COPY(QDragLeaveEvent);
public:
QDragLeaveEvent();
~QDragLeaveEvent();
}; //完结 class QDragLeaveEvent : public QEvent
(4) QDropEvent 是个小基类 :
/*
The QDropEvent class provides an event which is sent when a
drag and drop action is completed. 拖放完成时触发本事件。
Detailed Description :
当小部件接受拖放事件时,
如果它已经接受了最近发送给它的QDragEnterEvent或QDragMoveEvent,则会接收到此事件.
这个拖放事件包含一个拟议的操作,该操作可通过`proposedAction()、函数获取,以便该小部件可以接受或忽略。
如果该操作可由该小部件外理,应调用`acceptProposedAction()'函数。
由于拟议的操作可能由`Qt:DropAction`值的组合构成,
因此可能有必要选择其中一个值作为默认操作,或者要求用户选择他们偏好的操作。
如果拟议的拖放操作不合适,或许是因为您的自定义小部件不支持该操作,
您可以通过调用setDropAction()、并传入您偏好的操作来替换它。
如果设置的值不在`possibleActions()返回的按位或组合值中,将使用默认的复制操作。
一旦设置了替换拖放操作,应调用`accept()而非`acceptProposedAction()“来完成拖放操作。
mimeData ()'函数以QMimeData对象的形式提供在widget上放置的数据。
该对象除了包含数据本身外,还包含有关数据的MIME类型的信息。
*/
class Q_GUI_EXPORT QDropEvent : public QEvent
{
Q_EVENT_DISABLE_COPY(QDropEvent);
protected:
friend class QApplication;
QPointF m_pos ; //发生本事件时的位置信息
Qt::MouseButtons m_mouseState ; //指出鼠标按键是哪个,左中右
Qt::KeyboardModifiers m_modState ; //键盘修饰符:ctrl、alt、shift
Qt::DropActions m_actions ; //允许的拖放操作集合。
Qt::DropAction m_dropAction ;
Qt::DropAction m_defaultAction; //默认的建议的拖放操作
const QMimeData * m_data ;
/*
enum DropAction { //本枚举类用于描述模型视图里的拖动操作的语义:复制、剪切或超链接。
CopyAction = 0x 1, //Copy the data to the target.
MoveAction = 0x 2, //Move the data from the source to the target.
LinkAction = 0x 4, //Create a link from the source to the target.
ActionMask = 0x ff,
TargetMoveAction = 0x8002, //在 Windows上,当 D&D数据的所有权应被目标应用程序接管时,
//即源应用程序不应删除这些数据时,会使用此值。
//在X11上,此值用于执行移动操作。Mac上不使用TargetMoveAction。
IgnoreAction = 0x 0 //Ignore the action (do nothing with the data).
};
Q_DECLARE_FLAGS(DropActions, DropAction)
Q_DECLARE_OPERATORS_FOR_FLAGS(DropActions)
*/
public:
//Constructs a drop event of a certain type corresponding to a drop at the
// point specified by pos in the destination widget's coordinate system.
//The actions indicate which types of drag and drop operation can be performed,
// and the drag data is stored as MIME-encoded data in data.
//The states of the mouse buttons and keyboard modifiers at the
// time of the drop are specified by buttons and modifiers.
//在目标窗体的 pos坐标处,发生了本事件,事件类型默认是 Drop,允许的拖放行为是 actions,
//包含的 MIME数据是 data,此时对应的鼠标和键盘状态是 buttons和 modifiers。
QDropEvent( const QPointF & pos, Qt::DropActions actions, const QMimeData * data,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Type type = Drop); // enum QEvent::Type { Drop = 63 };
/*
enum QEvent::Type {
DragEnter = 60, // drag moves into widget 拖放进入
DragMove = 61, // drag moves in widget 拖放在移动
DragLeave = 62, // drag leaves or is cancelled 拖放离开或取消
Drop = 63, // actual drop 拖放完成
DragResponse = 64, // drag accepted/rejected
};
*/
~QDropEvent();
QDropEvent * clone() const override { return new QDropEvent(* this); }
QPointF position () const { return m_pos ; }
inline
Qt::MouseButtons buttons () const { return m_mouseState ; }
inline
Qt::KeyboardModifiers modifiers() const { return m_modState ; }
inline //Returns an OR-combination of possible drop actions.
Qt::DropActions possibleActions() const { return m_actions ; }
//返回目标对数据应执行的操作。如果已调用 setDropAction()以明确选择某个删除操作,
//则此操作可能与 proposedAction()中提供的操作有所不同。
inline
Qt::DropAction dropAction () const { return m_dropAction ; }
inline //Returns the proposed drop action.
Qt::DropAction proposedAction () const { return m_defaultAction; }
inline //返回放置在小部件上的数据及其关联的MIME类型信息。
const QMimeData * mimeData() const { return m_data ; }
//Sets the action to be performed on the data by the target.
//设置目标要对数据执行的操作。使用此选项来用可能的其他操作覆盖建议的操作。
//Use this to override the proposed action with one of the possible actions.
//如果你设置的拖放操作不是可能的操作之一,拖放操作将默认为复制操作。
//If you set a drop action that is not one of the possible actions,
// the drag and drop operation will default to a copy operation.
//一旦你提供了替换的删除操作,请调用accept()而不是acceptProposedAction()。
//Once you have supplied a replacement drop action,
// call accept() instead of acceptProposedAction().
void setDropAction (Qt::DropAction action);
inline //Sets the drop action to be the proposed action.
void acceptProposedAction () //采用系统建议的拖放操作
{
m_dropAction = m_defaultAction;
accept();
}
//如果拖拽操作的来源是此应用程序中的某个小部件,则该函数将返回该来源;否则,它将返回 nullptr。
//操作的来源是用于创建拖拽的 QDrag 对象的第一个参数。
//如果您的小部件在拖动到自身时需要特殊行为,则此功能很有用。
QObject * source() const;
}; //完结 class QDropEvent : public QEvent
(5) QDragMoveEvent 继承于上面的 QDropEvent :
/*
The QDragMoveEvent class provides an event which is sent while a
drag and drop action is in progress. 拖放移动事件
Detailed Description :
当拖拽操作在某个小部件的边界内进行时,这个小部件将反复接收到拖移事件和进入事件。
这个小部件应检查事件以确定其提供了何种数据,并在适当情况下调用“accept”()函数来接受拖放操作。
由`answerRect()、函数提供的矩形可以被用来限制放置操作仅限于控件的特定区域。
例如,我们可以检查该矩形是否与某个子控件的几何形状相交,
并且只有在相交的情况下才调用“acceptProposedAction()“方法。
请注意,此类从QDropEvent继承了大部分功能。
*/
class Q_GUI_EXPORT QDragMoveEvent : public QDropEvent
{
Q_EVENT_DISABLE_COPY(QDragMoveEvent);
protected:
QRect m_rect; //class QRect { int x1; int y1; int x2; int y2; };
public:
//Creates a QDragMoveEvent of the required type indicating that the
// mouse is at position pos given within a widget.
//The mouse and keyboard states are specified by buttons and modifiers,
//and the actions describe the types of drag and drop operation that are possible.
//The drag data is passed as MIME-encoded information in data.
//在组件内的 pos位置发生了 DragMove事件。actions 是允许的拖放事件集合。
//同时的鼠标与键盘状态是 buttons 与 modifiers。本事件的类型默认是 DragMove。
QDragMoveEvent( const QPoint & pos,
Qt::DropActions actions, const QMimeData * data,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Type type = DragMove);
//警告:不要尝试自己创建QDragMoveEvent。这些对象依赖于Qt的内部状态。
~QDragMoveEvent();
QDragMoveEvent * clone() const override { return new QDragMoveEvent(* this); }
//Returns the rectangle in the widget where the drop will occur if accepted.
//返回将在该小部件中发生放置操作的矩形区域。
//您可以利用这些信息来限制放置操作只能在小部件上的特定位置进行。
inline QRect answerRect() const { return m_rect; }
//void QEvent::accept () { m_accept = true ; } //覆盖了基类 QEvent里的同名成员函数。
inline void accept() { QDropEvent::accept() ; } //This is an overloaded function.
inline void accept(const QRect & rectangle) { accept(); m_rect = rectangle; }
//The same as accept(), //形参矩形里的拖放事件才被允许
// but also notifies that future moves will also be acceptable if they
// remain within the rectangle given on the widget.
//This can improve performance, but may also be ignored by the underlying system.
//If the rectangle is empty, drag move events will be sent continuously.
//This is useful if the source is scrolling in a timer event.
//void QEvent::ignore () { m_accept = false ; }
inline void ignore() { QDropEvent::ignore() ; } //This is an overloaded function.
inline void ignore(const QRect & r) { ignore(); m_rect = r; }
//The opposite of the accept(const QRect&) function. //形参矩形里的拖放事件将被忽略。
//Moves within the rectangle are not acceptable, and will be ignored.
}; //完结 class QDragMoveEvent : public QDropEvent
(6)孙子类 QDragEnterEvent 是内容较少的 :
/*
The QDragEnterEvent class provides an event which is sent to a
widget when a drag and drop action enters it.
QDragEnterEvent类提供了一个事件,当拖放操作进入一个部件时发送给该部件。
-个小部件必须接受此事件,以便在拖放操作进行期间接收发送的拖移DragMove事件。
拖入DragEnter事件总是紧接着一个拖移DragMove事件。
QDragEnterEvent大部分功能继承自QDragMoveEvent,而QDragMoveEvent又大部功能继承自 QDropEvent。
*/
class Q_GUI_EXPORT QDragEnterEvent : public QDragMoveEvent
{
Q_EVENT_DISABLE_COPY(QDragEnterEvent);
public:
//Constructs a QDragEnterEvent that represents a drag entering a widget at the
// given pos with mouse and keyboard states specified by buttons and modifiers.
//The drag data is passed as MIME-encoded information in data,
// and the specified actions describe the possible types of drag and
// drop operation that can be performed.
//发生了 DragEnter事件,地点在 pos ,同时的鼠标与键盘状态是 buttons和 modifiers。
//可能发生的拖放事件集合是 actions,附带的数据是 MIME格式的 data。
QDragEnterEvent(const QPoint & pos,
Qt::DropActions actions, const QMimeData * data,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
//警告:不要自己创建QDragEnterEvent,因为这些对象依赖于Qt的内部状态。
~QDragEnterEvent();
}; //完结 class QDragEnterEvent : public QDragMoveEvent
(7)
谢谢