Reputation: 4180
I am trying to create a small app using wxpython
where a user can drag some text from a listctrl
object (the source) and drop it in another listctrl
object (the target).
I would like to write this app in such a way that an text string is dropped into the target listctrl
object only if the cursor is in the target listctrl
area. My code (shown below) right now will drop a text string even if the cursor never moves into the target area. Any pointer would be greatly appreciated!
import wx
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
class TextDropTargetListCtrl(wx.TextDropTarget):
def __init__(self, object):
wx.TextDropTarget.__init__(self)
self.object = object
def OnDropText(self, x, y, data):
self.object.InsertStringItem(0, data)
def OnDragOver(self, x, y, d):
return wx.DragCopy
class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
def __init__(self, parent, style):
wx.ListCtrl.__init__(self, parent, -1, style=style)
ListCtrlAutoWidthMixin.__init__(self)
class MainApp(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="", size=(500, 800))
self.SetBackgroundColour('white')
self.GridBagSizer = wx.GridBagSizer()
self.listctrl_left = AutoWidthListCtrl(self, style = wx.LC_REPORT|wx.LC_VRULES)
self.listctrl_left.InsertColumn(0, "Source")
self.listctrl_left.InsertStringItem(0, "apple")
self.listctrl_left.InsertStringItem(1, "pear")
self.listctrl_left.InsertStringItem(2, "watermelon")
self.listctrl_right = AutoWidthListCtrl(self, style = wx.LC_REPORT)
self.listctrl_right.InsertColumn(0, "Destination")
self.GridBagSizer.Add(self.listctrl_left, pos=(0, 0),span = (1, 1),
flag = wx.EXPAND|wx.ALL, border = 15)
self.GridBagSizer.Add(self.listctrl_right, pos=(0, 1),span = (1, 1),
flag = wx.EXPAND|wx.ALL, border = 15)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit)
self.DropTarget = TextDropTargetListCtrl(self.listctrl_right)
self.GridBagSizer.AddGrowableCol(0)
self.GridBagSizer.AddGrowableCol(1)
self.GridBagSizer.AddGrowableRow(0)
self.SetSizer(self.GridBagSizer)
def OnDragInit(self, evt):
text = self.listctrl_left.GetItemText(evt.GetIndex())
tdo = wx.TextDataObject(text)
tds = wx.DropSource(self.listctrl_left)
tds.SetData(tdo)
tds.DoDragDrop(True)
if __name__ == "__main__":
app = wx.App()
MainFrame = MainApp()
MainFrame.Show()
MainFrame.Centre()
app.MainLoop()
Upvotes: 0
Views: 459
Reputation: 2710
import wx
from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
class TextDropTargetListCtrl(wx.TextDropTarget):
def __init__(self, object, parent):
wx.TextDropTarget.__init__(self)
self.object = object
self.parent = parent
def OnDropText(self, x, y, data):
_x,_y = self.parent.listctrl_right.GetPosition()
_w,_h = self.parent.listctrl_right.GetSize()
# print _x, _w
# if self.parent.hovering:
if _x < x < _x+_w:
self.object.InsertStringItem(0, data)
def OnDragOver(self, x, y, d):
return wx.DragCopy
class AutoWidthListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
def __init__(self, parent, style):
wx.ListCtrl.__init__(self, parent, -1, style=style)
ListCtrlAutoWidthMixin.__init__(self)
class MainApp(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="", size=(500, 800))
self.SetBackgroundColour('white')
self.GridBagSizer = wx.GridBagSizer()
self.listctrl_left = AutoWidthListCtrl(self, style = wx.LC_REPORT|wx.LC_VRULES)
self.listctrl_left.InsertColumn(0, "Source")
self.listctrl_left.InsertStringItem(0, "apple")
self.listctrl_left.InsertStringItem(1, "pear")
self.listctrl_left.InsertStringItem(2, "watermelon")
self.listctrl_right = AutoWidthListCtrl(self, style = wx.LC_REPORT)
self.listctrl_right.InsertColumn(0, "Destination")
# self.listctrl_right.Bind(wx.EVT_ENTER_WINDOW, self.OnHoverEnter)
# self.listctrl_right.Bind(wx.EVT_LEAVE_WINDOW, self.OnHoverLeave)
# self.hovering = False
self.GridBagSizer.Add(self.listctrl_left, pos=(0, 0),span = (1, 1),
flag = wx.EXPAND|wx.ALL, border = 15)
self.GridBagSizer.Add(self.listctrl_right, pos=(0, 1),span = (1, 1),
flag = wx.EXPAND|wx.ALL, border = 15)
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDragInit)
self.DropTarget = TextDropTargetListCtrl(self.listctrl_right, self)
self.GridBagSizer.AddGrowableCol(0)
self.GridBagSizer.AddGrowableCol(1)
self.GridBagSizer.AddGrowableRow(0)
self.SetSizer(self.GridBagSizer)
# def OnHoverEnter(self, event):
# self.hovering = True
# def OnHoverLeave(self, event):
# self.hovering = False
def OnDragInit(self, evt):
text = self.listctrl_left.GetItemText(evt.GetIndex())
tdo = wx.TextDataObject(text)
tds = wx.DropSource(self.listctrl_left)
tds.SetData(tdo)
tds.DoDragDrop(True)
# evt.Skip()
if __name__ == "__main__":
app = wx.App()
MainFrame = MainApp()
MainFrame.Show()
MainFrame.Centre()
app.MainLoop()
This is very hackish but does what you want... Initially I tried EVT_ENTER_WINDOW
and EVT_LEAVE_WINDOW
events, which worked ok on listctrl but not while dragging. So, I just checked if the x coordinate of drop event falls within the right listctrl widget or not.
Upvotes: 1