Drag and Drop questions

Hi all
I am trying to implement a generic drag and drop system to use in my wx applications.
I have many question about DnD in wx and i hope you can help me :slight_smile:

  I am able to use the standard DnD way using wx.DropSource, wx.DataObject and wx.DropTarget but i have some unresolved issues:

1) How can I drag a bitmap of the dragged object ? I see that i can use cursor or icons but it seems that i cannot use a bitmap. Any trick to do it ?

2) How can I accept a drag from a customtreectrl item ? It seems that DnD in this control only works inside the control itself. I am able to modify the code to move dragged image outside the control but of course it is not able to trigger the drop.

3) I tried also to perform the drag using the wxDragImage class and it works. But I have problems to get a visual feedback. I tried using wx.ScreenDC and wx.ClientDc to draw a rect arount the object but the result is ugly.

Any suggestion ?

G.

p.s. sorry for my english :wink:

Porcari Giovanni wrote:

Hi all
I am trying to implement a generic drag and drop system to use in my wx applications.
I have many question about DnD in wx and i hope you can help me :slight_smile:

I am able to use the standard DnD way using wx.DropSource, wx.DataObject and wx.DropTarget but i have some unresolved issues:

1) How can I drag a bitmap of the dragged object ? I see that i can use cursor or icons but it seems that i cannot use a bitmap. Any trick to do it ?

You can override GiveFeedback in a class derived from wx.DropSource, and then do something there to move a bitmap around with the mouse.

2) How can I accept a drag from a customtreectrl item ? It seems that DnD in this control only works inside the control itself. I am able to modify the code to move dragged image outside the control but of course it is not able to trigger the drop.

This applies to the regular wx.TreeCtrl too since the CustomTreeCtrl started out as a Python port of the stock generic C++ treectrl code. You are correct, the DnD built-in to the tree is only for the tree. The way that dragging out of the tree is usually done is to just use the regular DnD instead of the tree's. Just catch the EVT_TREE_BEGIN_DRAG event do it from there.

3) I tried also to perform the drag using the wxDragImage class and it works. But I have problems to get a visual feedback. I tried using wx.ScreenDC and wx.ClientDc to draw a rect arount the object but the result is ugly.

Which? The source, the target? the dragged image?

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Hi Giovanni,

    you may consider these snippets of code as a starting point:

import wx
import cPickle

class DragInfo:

    def __init__(self, data):
        """ Default class constructor. """

        self._data = data

    def GetPlotData(self):
        """ Returns the data to plot in the MatPlotLib canvas. """

        return self._data

<snip> subclassing of CustomTreeCtrl and initialization (self is a
CustomTreeCtrl):

self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag)

    def OnBeginDrag(self, event):

        item = event.GetItem()
        if not item:
            event.Skip()
            return

        data = self.GetDataFromItem(item)

        if not data:
            event.Skip()
            return

        event.Allow()

        draginfo = cPickle.dumps(DragInfo(data))
        dataobject = wx.CustomDataObject(wx.CustomDataFormat("SymphonyPlot"))
        dataobject.SetData(draginfo)
        dragSource = wx.DropSource(self)
        dragSource.SetData(dataobject)
        dragSource.DoDragDrop(wx.Drag_DefaultMove)
        event.Skip()

In your other class, your droptarget, you could do something like:

class DropTarget(wx.DropTarget):

    def __init__(self, parent):
        """ Default class constructor. """

        wx.DropTarget.__init__(self)

        self._parent = parent
        self._dataobject =
wx.CustomDataObject(wx.CustomDataFormat("SymphonyPlot"))
        self.SetDataObject(self._dataobject)

    def OnData(self, x, y, dragres):
        """ Handles the OnData() method to call the real DnD routine. """

        if not self.GetData():
            return wx.DragNone

        draginfo = self._dataobject.GetData()
        drginfo = cPickle.loads(draginfo)

        if not drginfo.GetPlotData():
            return wx.DragNone

        return self._parent.OnDropTarget(x, y, drginfo.GetPlotData())

Above, "_parent" is your drop target (that may be a panel, a button,
whatever you want). At last, you have in your "_parent" class a method
like:

    def OnDropTarget(self, x, y, data):
        """ Handles the drop action from a DND operation. """

        if not data:
            return wx.DragCancel

        # do whatever you want with your data
        return wx.DragMove

Hope this helps. Sorry if I could not put a complete example here, but
it's bed-time for me :wink:

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.virgilio.it/infinity77/

Porcari Giovanni wrote:

Hi all
I am trying to implement a generic drag and drop system to use in my wx
applications.
I have many question about DnD in wx and i hope you can help me :slight_smile:

I am able to use the standard DnD way using wx.DropSource,
wx.DataObject and wx.DropTarget but i have some unresolved issues:

  1. How can I drag a bitmap of the dragged object ? I see that i can use

cursor or icons but it seems that i cannot use a bitmap. Any trick to do
it ?

You can override GiveFeedback in a class derived from wx.DropSource, and
then do something there to move a bitmap around with the mouse.

I’m trying it now but I was no able to find examples and I cannot figure how can I have drag the bitmap. I suppose that I have to read mouse position and use a ScreenDC to draw the bitmap. Or there is an easier way ?

  1. How can I accept a drag from a customtreectrl item ? It seems that

DnD in this control only works inside the control itself. I am able to
modify the code to move dragged image outside the control but of course
it is not able to trigger the drop.

This applies to the regular wx.TreeCtrl too since the CustomTreeCtrl
started out as a Python port of the stock generic C++ treectrl code.
You are correct, the DnD built-in to the tree is only for the tree. The
way that dragging out of the tree is usually done is to just use the

regular DnD instead of the tree’s. Just catch the EVT_TREE_BEGIN_DRAG
event do it from there.

I see. Ok… I’ll try in this way.

  1. I tried also to perform the drag using the wxDragImage class and it
    works. But I have problems to get a visual feedback. I tried using
    wx.ScreenDC and wx.ClientDc to draw a rect arount the object but the

result is ugly.

Which? The source, the target? the dragged image?

When I use the wx.DragImage i use wx.FindWindowAtPoint(pt) to know the target.
Then i try to highlight it drawing a rectangle inside when the dragged bitmap enters in the target and again when it exit to erase it.

    dc=wx.ClientDC(win)
    dc.SetBrush(wx.TRANSPARENT_BRUSH)
    dc.SetPen(wx.Pen('BLUE',1,wx.SOLID))
    dc.SetLogicalFunction(wx.INVERT)
    w,h=win.GetSizeTuple()
    dc.DrawRectangle

(0,4,w-4,h-8)

Unfortunately nothing happen. So I tryed without dc.SetLogicalFunction(wx.INVERT) and I have my rectangle but of course it remains forever…

I really need to see some good code to learn :wink:

Thank you again

G

···

2006/11/8, Robin Dunn robin@alldunn.com:


Robin Dunn
Software Craftsman

http://wxPython.org
Java give you jitters? Relax with wxPython!


To unsubscribe, e-mail:
wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Giovanni Porcari wrote:

2006/11/8, Robin Dunn <robin@alldunn.com <mailto:robin@alldunn.com>>:

    Porcari Giovanni wrote:
     > Hi all
     > I am trying to implement a generic drag and drop system to use in
    my wx
     > applications.
     > I have many question about DnD in wx and i hope you can help me :slight_smile:
     >
     > I am able to use the standard DnD way using wx.DropSource,
     > wx.DataObject and wx.DropTarget but i have some unresolved issues:
     >
     > 1) How can I drag a bitmap of the dragged object ? I see that i
    can use
     > cursor or icons but it seems that i cannot use a bitmap. Any
    trick to do
     > it ?

    You can override GiveFeedback in a class derived from wx.DropSource, and
    then do something there to move a bitmap around with the mouse.

I'm trying it now but I was no able to find examples and I cannot figure how can I have drag the bitmap. I suppose that I have to read mouse position and use a ScreenDC to draw the bitmap. Or there is an easier way ?

Or use a wx.DragImage and update its position to where the mouse is, or use a small shaped window and have it follow the mouse, or some other idea...

     > 3) I tried also to perform the drag using the wxDragImage class
    and it
     > works. But I have problems to get a visual feedback. I tried using
     > wx.ScreenDC and wx.ClientDc to draw a rect arount the object but
    the
     > result is ugly.

    Which? The source, the target? the dragged image?

When I use the wx.DragImage i use wx.FindWindowAtPoint(pt) to know the target.
Then i try to highlight it drawing a rectangle inside when the dragged bitmap enters in the target and again when it exit to erase it.

When using real DnD you can handle these kinds of things in the drop target class' OnEnter, OnDragOver, etc.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

Just to say thank you to Robin and Andrea.

Now my generic DnD works :slight_smile:

This is the class I use:

class _GnrWxDropSource(wx.DropSource):
     def __init__(self,win, curCopy=None, curMove=None, curVeto=None):
         blankCursor= wx.StockCursor(wx.CURSOR_HAND)
         curCopy= curCopy or blankCursor
         curMove= curMove or blankCursor
         curVeto= curVeto or blankCursor
         self.win=win
         bmp=win.createBitmap()
         self.dragImage = wx.DragImage(bmp)
         self.dragImage.BeginDrag(wx.Point(bmp.GetWidth()/2,bmp.GetHeight()/2),
                                                    win, fullScreen=True)
         self.dragImage.Show()
         wx.DropSource.__init__(self,obj.wxref, curCopy , curMove, curVeto)

     def GiveFeedback(self,x):
         pt=self.win.ScreenToClient(wx.GetMousePosition())
         self.dragImage.Move(pt)
         return False

I have only a little square rect moving around with my image and I have no idea to avoid it.

Thank you again :slight_smile:

G.

···

Il giorno 09/nov/06, alle ore 01:44, Robin Dunn ha scritto:

Giovanni Porcari wrote:

2006/11/8, Robin Dunn <robin@alldunn.com <mailto:robin@alldunn.com>>:
    Porcari Giovanni wrote:
     > Hi all
     > I am trying to implement a generic drag and drop system to use in
    my wx
     > applications.
     > I have many question about DnD in wx and i hope you can help me :slight_smile:
     >
     > I am able to use the standard DnD way using wx.DropSource,
     > wx.DataObject and wx.DropTarget but i have some unresolved issues:
     >
     > 1) How can I drag a bitmap of the dragged object ? I see that i
    can use
     > cursor or icons but it seems that i cannot use a bitmap. Any
    trick to do
     > it ?
    You can override GiveFeedback in a class derived from wx.DropSource, and
    then do something there to move a bitmap around with the mouse. I'm trying it now but I was no able to find examples and I cannot figure how can I have drag the bitmap. I suppose that I have to read mouse position and use a ScreenDC to draw the bitmap. Or there is an easier way ?

Or use a wx.DragImage and update its position to where the mouse is, or use a small shaped window and have it follow the mouse, or some other idea...

     > 3) I tried also to perform the drag using the wxDragImage class
    and it
     > works. But I have problems to get a visual feedback. I tried using
     > wx.ScreenDC and wx.ClientDc to draw a rect arount the object but
    the
     > result is ugly.
    Which? The source, the target? the dragged image?
When I use the wx.DragImage i use wx.FindWindowAtPoint(pt) to know the target.
Then i try to highlight it drawing a rectangle inside when the dragged bitmap enters in the target and again when it exit to erase it.

When using real DnD you can handle these kinds of things in the drop target class' OnEnter, OnDragOver, etc.

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org