I'm working on a window that is a drag source. But it does not provide
data for dragging. Instead it tires to send itself for the drag drop
handler. The idea is that there are dragging operations between
similar widgets. These widgets are connected to the same data model.
The drag operations are ending in method calls of the data model, and
they change the state of the data model. After any state change, many
or all of the widgets needs to be updated. E.g. there is no "data" to
be dragged.
So I created this function, that stores the "drag source" widget in a
global variable:
def start_drag(ident,source):
global _dragged
_dragged = weakref.ref(source)
# Create custom data object with your format.
format = ident_to_format(ident)
data = wx.CustomDataObject(format)
data.SetData("1")
return data
There can only be one drag operation in progress, so the same _dragged
global variable can be used for all "dataless" dragging operations.
The widgets connected to the data model are wx.Window descendants, and
they are drawn completely from Python. From a widget like this, here
are some code snippets:
# Event for dragging, should be similar to EVT_LIST_BEGIN_DRAG but it
is a custom widget so I guess I need a custom event?
DimensionDragEvent, EVT_DIMENSION_DRAG = wx.lib.newevent.NewEvent()
class DimensionPanem(wx.Window):
def __init__(self,parent,id,model):
wx.Window.__init__(self,parent,id)
self.model = model
self._src_ident = model.get_ident() # Identifies the model,
this is a string
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_LEFT_DOWN,self.LeftDown,self)
self.Bind(EVT_DIMENSION_DRAG ,self.datalessStartDrag,self)
# .... more code here ...
def OnPaint(self,event):
# .... display state/view of self.model here!
def OnLeftDown(self,event):
# Start dragging operation when the user presses left
mouse button
evt = DimensionDragEvent(x=event.GetX(),y=event.GetY())
wx.PostEvent(self, evt)
def datalessStartDrag(self, evt):
# Called when we need to start dragging.
# Create a tricky data object for this data model + source
widget
data = start_drag(self._src_ident,self)
# Create drop source and begin drag-and-drop.
dropSource = wx.DropSource(self)
dropSource.SetData(data)
res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove) # <---
this is where the problem is!
print "DoDragDrop returned",res # Print result of the drag
operation
So I try to start the drag operation when the user presses left mouse
button. My problem is that when I left click on the source widget, the
DoDragDrop returns immediately. E.g. after left clicking on the source
widget, the application prints:
DoDragDrop returned 1
I don't understand WHEN the DoDragDrop call is supposed to return? How
do I control this from my program? I would like to end the drag
operation in the following cases:
* user releases left mouse button over a drop target that is capable
of accepting the drag source. (This can be done with a PyDropTarget,
that check if the source widget is connected to the same model or
not). In this case, the data model needs to be changed/method called.
* user releases left mouse button over something else, in this case
the drag operation should be cancelled.
How can I do the second part? I was reading this wiki:
http://wiki.wxpython.org/DragAndDrop but It does not tell WHEN and HOW
DoDragDrop returns? It only tells that it will return, eventually...
Thanks,
Laszlo