2016-06-01 17 views
0
.

. Я пытаюсь создать небольшое приложение, используя wxpython, где пользователь может перетащить какой-либо текст из объекта listctrl (источник) и отбросить его в другом listctrl объект (цель).wxpython drag and drop: drop, только если курсор находится внутри целевого объекта listctrl.

Я хотел бы написать это приложение таким образом, что текстовая строка упала в объект целевого listctrl только тогда, когда курсор находится в целевом listctrl области. Мой код (показано ниже) прямо сейчас удалит текстовую строку, даже если курсор никогда не перемещается в целевую область. Любой указатель будет очень благодарен!

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() 
+0

возможно поймать 'wx.EVT_SET_FOCUS' и сохранить это в флагом и установить этот флажок в' OnDropText'? ср http://stackoverflow.com/questions/25899489/how-to-write-wxpython-textctrl-focus-event – otterb

+0

Вы имеете в виду, что ваш 'TextDropTargetListCtrl :: OnDropText' выполняется даже тогда, когда курсор не превышает' listctrl_right'? Я не понимаю, как это могло произойти, может быть, я неправильно понял описание проблемы? –

+0

@VZ. Это именно то, что происходит. – Alex

ответ

1
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() 

Это очень хак, но делает то, что вы хотите ... Сначала я попытался EVT_ENTER_WINDOW и EVT_LEAVE_WINDOW события, которые работали нормально на ListCtrl но не при перетаскивании. Итак, я просто проверял, попадает ли координата x в событие drop в правый виджет listctrl или нет.

+0

Спасибо! Это прекрасно работает. – Alex