Jan Holthuis
Jan Holthuis

Reputation: 181

How to use wxpython's DataViewCtrl Drag and Drop

I want to use drag&drop in combination with wx.dataview.DataViewCtrl, so I started with trying to reorder rows using Drag&Drop. I was unable to find any examples how to do this correctly in wxpython, but anyhow, I managed to get it partially working (see below).

Unfortunately, event.GetDataObject() always returns None in my on_drop function. Any pointers how to get the DataObject I assigned in on_begin_drag? What am I doing wrong?

Thanks in advance!

Setup:

Example Code:

import wx
import wx.dataview

DF_PLAYLIST_SONG = wx.CustomDataFormat("playlist_song")

class MyDataViewCtrl(wx.dataview.DataViewCtrl)
  def __init__(self, *args. **kwargs)
    [...]
    self.Bind(wx.dataview.EVT_DATAVIEW_ITEM_BEGIN_DRAG, self.on_begin_drag)
    self.Bind(wx.dataview.EVT_DATAVIEW_ITEM_DROP, self.on_drop)

    self.EnableDragSource(DF_PLAYLIST_SONG)
    self.EnableDropTarget(DF_PLAYLIST_SONG)

  [...]

  def on_begin_drag(self, event):
    text = self._model.GetValue(event.GetItem(), 0)
    data = wx.CustomDataObject(DF_PLAYLIST_SONG)
    # Need to encode, because SetData dislikes unicode
    data.SetData(text.encode('utf-8'))
    event.SetDataObject(data)
    #data.this.disown() # Makes no difference if uncommented or not

  def on_drop(self, event):
    print(event.GetDataFormat()) # Returns DF_PLAYLIST_SONG
    if event.GetDataFormat() == DF_PLAYLIST_SONG:
      # This would be logical choice:
      print(event.GetDataSize()) # Returns the size of the data, e.g 92
      print(event.GetDataObject()) # Returns None (strange!)
      # Some other stuff I tried
      print(event.GetClientObject()) # Returns MyDataViewCtrl instance
      print(event.GetEventObject()) # Returns None
      print(event.GetValue()) # Returns <Swig Object of type 'wxVariant *' at 0x7fffa340a0d0>
      print(self._model.GetValue(event.GetItem(), 0)) # Returns column 0 of the row this was dropped on
      print(event.GetItem()) # Returns the wx.dataview.DataViewItem this was dropped on
      print(event.GetDataBuffer()) # Returns <Swig Object of type 'void *' at 0x1a59b30>

Upvotes: 0

Views: 2097

Answers (2)

nepix32
nepix32

Reputation: 3177

See this example on a wxWidgets/wxPython ticket 15100. I used it to make drag/drop for a wx.DataViewCtrl and a tree-ish data structure happen (to get an object back). Works at least on 2.9.5/msw. HitTest has been implemented in 3.0.2 (if you want to know which item got hit).

May not be the proper answer for your problem but at least it does work (see the crazy pickling of the object item).

Upvotes: 0

VZ.
VZ.

Reputation: 22708

You don't get back the data object in wxEVT_DATAVIEW_ITEM_DROP hander, it's only used for dragging data away from the control. When dropping, you get the raw data and its format, i.e. you should use GetDataSize() and GetDataBuffer() to access it.

Upvotes: 1

Related Questions