You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

208 lines
6.6 KiB

.. _DnD:
=============
Drag and Drop
=============
Drag and drop provides a simple visual mechanism which users can use to transfer
information between and within widgets.
Drag and drop is similar in function to the clipboard's cut and paste mechanism.
.. image:: https://github.com/user-attachments/assets/857fd144-7a2a-4173-80b3-d135e62b8235
This document describes the basic drag and drop mechanism and outlines the
approach used to enable it in custom controls.
Drag and drop operations are also supported by many of TermTk's controls,
such as :py:class:`TTkList` or :py:class:`TTkTabWidget`.
---------------------
Drag and Drop Classes
---------------------
These classes deal with drag and drop and the necessary mime type encoding and decoding.
.. currentmodule:: TermTk
.. autosummary::
:caption: Classes:
:template: custom-class-template.01.rst
TTkGui.TTkDrag
TTkGui.TTkDropEvent
--------
Dragging
--------
To start a drag, create a :py:class:`TTkDrag` object, and call its :py:meth:`TTkDrag.exec` function.
In most applications, it is a good idea to begin a drag and drop operation only
after a mouse button has been pressed and the cursor has been moved a certain distance.
However, the simplest way to enable dragging from a widget is to reimplement
the widget's :py:meth:`TTkWidget.mouseDragEvent` and start a drag and drop operation:
.. code:: python
def mouseDragEvent(self, evt:ttk.TTkMouseEvent) -> bool:
if evt.key == ttk.TTkMouseEvent.LeftButton:
drag = ttk.TTkDrag()
drag.setData("LeftClick Drag")
drag.exec()
return True
Note that the :py:meth:`TTkDrag.exec` function does not block the main event loop.
.. seealso::
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.01.basic.py`
--------
Dropping
--------
To be able to receive the content dropped on a widget, reimplement
the :py:meth:`TDragEvents.dropEvent` event handler functions.
.. code:: python
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool:
ttk.TTkLog.debug(f"Drop data: {evt.data()}, Position: {evt.pos()}")
return True
.. seealso::
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.01.basic.py`
------
Events
------
There are several events that can be used to customize the drag and drop operation:
* :py:meth:`TDragEvents.dropEvent` - Called when a drag is dropped on the widget.
* :py:meth:`TDragEvents.dragEnterEvent` - Called when a drag enters the widget.
* :py:meth:`TDragEvents.dragMoveEvent` - Called when a drag moves over the widget.
* :py:meth:`TDragEvents.dragLeaveEvent` - Called when a drag leaves the widget if :py:meth:`TDragEvents.dragEnterEvent` or :py:meth:`TDragEvents.dragMoveEvent` are andled inside the widget.
.. code:: python
def dragEnterEvent(self, evt:ttk.TTkDnDEvent) -> bool:
ttk.TTkLog.debug(f"Drag Enter: {evt.data()}, Position: {evt.pos()}")
return True
def dragLeaveEvent(self, evt:ttk.TTkDnDEvent) -> bool:
ttk.TTkLog.debug(f"Drag Leave: {evt.data()}, Position: {evt.pos()}")
return True
def dragMoveEvent(self, evt:ttk.TTkDnDEvent) -> bool:
ttk.TTkLog.debug(f"Drag Move: {evt.data()}, Position: {evt.pos()}")
return True
def dropEvent(self, evt:ttk.TTkDnDEvent) -> bool:
ttk.TTkLog.debug(f"Drop: {evt.data()}, Position: {evt.pos()}")
return True
.. seealso::
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.02.events.01.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.02.events.02.py`
------
Pixmap
------
The visual representation of the drag can be customized by setting a pixmap with :py:meth:`TTkDrag.setPixmap`.
By default the pixmap is initialized as a simple text string ("[...]")
but it can be customized by using
a :py:class:`TTkWidget` or :py:class:`TTkCanvas` as a pixmap.
.. image:: https://github.com/user-attachments/assets/7a23f5a9-444b-4e5a-878b-91c4b35ee8d8
You can use the same object as pixmap to have a visual feedback of the widget being dragged:
.. code:: python
def mouseDragEvent(self, evt:ttk.TTkMouseEvent) -> bool:
drag = ttk.TTkDrag()
drag.setPixmap(self)
drag.exec()
return True
Or define another :py:class:`TTkWidget` as pixmap:
.. code:: python
def mouseDragEvent(self, evt:ttk.TTkMouseEvent) -> bool:
button = ttk.TTkButton(text=f"DnD", border=True, size=(25,5))
drag = ttk.TTkDrag()
drag.setPixmap(button)
drag.exec()
return True
Or use a :py:class:`TTkCanvas` as pixmap and draw the required content on it:
.. code:: python
def mouseDragEvent(self, evt:ttk.TTkMouseEvent) -> bool:
pixmap = ttk.TTkCanvas(width=17,height=5)
pixmap.drawText(pos=(0,0),text="╭╼ TXT ╾────────╮")
pixmap.drawText(pos=(0,1),text="│Lorem ipsum dol│")
pixmap.drawText(pos=(0,2),text="│consectetur adi│")
pixmap.drawText(pos=(0,3),text="│sed do eiusmod │")
pixmap.drawText(pos=(0,4),text="╰────────╼ End ╾╯")
drag = ttk.TTkDrag()
drag.setPixmap(pixmap)
drag.exec()
return True
.. seealso::
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.03.pixmap.01.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.03.pixmap.02.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.03.pixmap.03.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.03.pixmap.04.py`
-------
HotSpot
-------
The hotspot is the offset of the pixmap related to the cursor position.
It can be set using :py:meth:`TTkDrag.setHotSpot`.
It is useful when the pixmap is not centered on the cursor or when you want to define an offset to allow
the object being dragged from the clicked position:
.. image:: https://github.com/user-attachments/assets/8d999365-c787-4eff-84f2-03ef2b22c37a
.. code:: python
def mouseDragEvent(self, evt:ttk. TTkMouseEvent) -> bool:
drag = ttk.TTkDrag()
drag.setHotSpot((evt.x, evt.y))
drag.setPixmap(self)
drag.exec()
return True
.. seealso::
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.04.hotSpot.01.py`
--------
Examples
--------
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.01.basic.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.02.events.01.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.02.events.02.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.03.pixmap.01.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.03.pixmap.02.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.03.pixmap.03.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.03.pixmap.04.py`
* :ttk:sbIntLink:`tutorial/examples/DragAndDrop/dnd.04.hotSpot.01.py`