wxpython 拖放:仅当光标在目标 listctrl 对象内时才放下

wxpython drag and drop: drop only if the cursor is inside the target listctrl object

我正在尝试使用 wxpython 创建一个小型应用程序,用户可以在其中从 listctrl 对象(源)拖动一些文本并将其放入另一个 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()
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_WINDOWEVT_LEAVE_WINDOW 事件,它们在 listctrl 上运行正常,但 在拖动时没有运行 [=16] =].所以,我只是检查了 drop 事件的 x 坐标是否落在正确的 listctrl 小部件内。