Differences between revisions 4 and 5
Revision 4 as of 2020-03-14 18:16:06
Size: 9703
Editor: Ecco
Comment:
Revision 5 as of 2020-03-14 18:23:10
Size: 9939
Editor: Ecco
Comment:
Deletions are marked like this. Additions are marked like this.
Line 18: Line 18:
Here's how you can use drag-and-drop to reorder a simple list, or to move items from one list to another.
As it stands, item data will be lost. Maybe in version 2 !
Here's how you can use drag-and-drop to reorder a simple list, or to move items from one list to another. As it stands, item data will be lost. Maybe in version 2 !
Line 23: Line 22:
Line 24: Line 24:
Line 29: Line 30:
Line 30: Line 32:
Line 34: Line 37:
Line 38: Line 42:
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
Line 40: Line 46:

#---------------------------------------------------------------------------
    
#---------------------------------------------------------------------------
        
Line 48: Line 54:
        #------------
#------------
        
Line 52: Line 59:
        #------------
#------------
Line 54: Line 63:
        dl1.SetBackgroundColour("#e6ffd0")         dl1.SetBackgroundColour("#e6ffd0")         
Line 60: Line 70:
        
Line 62: Line 72:
Line 67: Line 78:

        #------------
            
        #------------
        
Line 71: Line 82:
Line 73: Line 85:
        
Line 76: Line 88:
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
Line 80: Line 94:
        #------------
#------------
        
Line 83: Line 98:
        #------------
#------------
        
Line 87: Line 103:
Line 88: Line 105:
        
Line 93: Line 110:
        
Line 101: Line 118:

Line 105: Line 124:
        
Line 113: Line 132:
Line 115: Line 135:
        # Create our own data format and use it         # Create our own data format and use it 
Line 122: Line 142:
Line 126: Line 147:
Line 130: Line 152:
Line 135: Line 158:

Line 139: Line 164:
Line 141: Line 167:
Line 152: Line 179:
Line 157: Line 185:
Line 166: Line 195:
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
Line 177: Line 208:
        #------------
#------------
        
Line 180: Line 212:
        #------------
#------------
        
Line 185: Line 218:
Line 186: Line 220:

    # Called when OnDrop returns True.
        
    # Called when OnDrop returns True.    
Line 193: Line 227:
        
Line 200: Line 234:
Line 204: Line 239:
#---------------------------------------------------------------------------
class MyApp(wx.App):

#---------------------------------------------------------------------------

class MyApp(wx.App):    
Line 207: Line 244:
        #------------
#------------
Line 211: Line 250:
Line 212: Line 252:

#---------------------------------------------------------------------------
    
#---------------------------------------------------------------------------
Line 217: Line 258:
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------

List control and drag and drop - DnD (Phoenix)

Keywords : ListCtrl, Drag and drop.


Demonstrating :

Tested py3.x, wx4.x and Win10.

Are you ready to use some samples ? ;)

Test, modify, correct, complete, improve and share your discoveries ! (!)


Sample one

img_sample_one.png

Here's how you can use drag-and-drop to reorder a simple list, or to move items from one list to another. As it stands, item data will be lost. Maybe in version 2 !

Toggle line numbers
   1 # sample_one.py
   2 
   3 """
   4 
   5 Drag and drop (DnD) demo with listctrl :
   6 - Dragging of multiple selected items.
   7 - Dropping on an empty list.
   8 - Dropping of items on a list with a different number of columns.
   9 - Dropping on a different applications.
  10 
  11 """
  12 
  13 import pickle
  14 import sys
  15 from   random import choice
  16 import wx
  17 
  18 # class MyFrame
  19 # class MyDragList
  20 # class MyListDrop
  21 # class MyApp
  22 
  23 #---------------------------------------------------------------------------
  24 
  25 items = ['Foo', 'Bar', 'Baz', 'Zif', 'Zaf', 'Zof']
  26     
  27 #---------------------------------------------------------------------------
  28         
  29 class MyFrame(wx.Frame):
  30     def __init__(self, parent, id):
  31         wx.Frame.__init__(self, parent, id,
  32                           "Sample one",
  33                           size=(450, 295))
  34 
  35         #------------
  36         
  37         self.SetIcon(wx.Icon('wxwin.ico'))
  38         self.SetMinSize((450, 295))
  39 
  40         #------------
  41 
  42         dl1 = MyDragList(self, style=wx.LC_LIST)
  43         dl1.SetBackgroundColour("#e6ffd0")        
  44 
  45         dl2 = MyDragList(self, style=wx.LC_REPORT)
  46         dl2.InsertColumn(0, "Column - 0", wx.LIST_FORMAT_LEFT)
  47         dl2.InsertColumn(1, "Column - 1", wx.LIST_FORMAT_LEFT)
  48         dl2.InsertColumn(2, "Column - 2", wx.LIST_FORMAT_LEFT)
  49         dl2.SetBackgroundColour("#f0f0f0")
  50         
  51         maxs = -sys.maxsize - 1
  52 
  53         for item in items:
  54             dl1.InsertItem(maxs, item)
  55             idx = dl2.InsertItem(maxs, item)
  56             dl2.SetItem(idx, 1, choice(items))
  57             dl2.SetItem(idx, 2, choice(items))
  58             
  59         #------------
  60         
  61         sizer = wx.BoxSizer(wx.HORIZONTAL)
  62 
  63         sizer.Add(dl1, proportion=1, flag=wx.EXPAND)
  64         sizer.Add(dl2, proportion=1, flag=wx.EXPAND)
  65         
  66         self.SetSizer(sizer)
  67         self.Layout()
  68 
  69 #---------------------------------------------------------------------------
  70 
  71 class MyDragList(wx.ListCtrl):
  72     def __init__(self, *arg, **kw):
  73         wx.ListCtrl.__init__(self, *arg, **kw)
  74 
  75         #------------
  76         
  77         self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
  78 
  79         #------------
  80         
  81         dt = MyListDrop(self)
  82         self.SetDropTarget(dt)
  83 
  84     #-----------------------------------------------------------------------
  85         
  86     def GetItemInfo(self, idx):
  87         """
  88         Collect all relevant data of a listitem, and put it in a list.
  89         """
  90         
  91         l = []
  92         l.append(idx) # We need the original index, so it is easier to eventualy delete it.
  93         l.append(self.GetItemData(idx)) # Itemdata.
  94         l.append(self.GetItemText(idx)) # Text first column.
  95         for i in range(1, self.GetColumnCount()): # Possible extra columns.
  96             l.append(self.GetItem(idx, i).GetText())
  97         return l
  98 
  99 
 100     def StartDrag(self, event):
 101         """
 102         Put together a data object for drag-and-drop _from_ this list.
 103         """
 104         
 105         l = []
 106         idx = -1
 107         while True: # Find all the selected items and put them in a list.
 108             idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
 109             if idx == -1:
 110                 break
 111             l.append(self.GetItemInfo(idx))
 112 
 113         # Pickle the items list.
 114         itemdata = pickle.dumps(l, 1)
 115         # Create our own data format and use it 
 116         # in a Custom data object.
 117         ldata = wx.CustomDataObject("ListCtrlItems")
 118         ldata.SetData(itemdata)
 119         # Now make a data object for the  item list.
 120         data = wx.DataObjectComposite()
 121         data.Add(ldata)
 122 
 123         # Create drop source and begin drag-and-drop.
 124         dropSource = wx.DropSource(self)
 125         dropSource.SetData(data)
 126         res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
 127 
 128         # If move, we want to remove the item from this list.
 129         if res == wx.DragMove:
 130             # It's possible we are dragging/dropping from this list to this list.
 131             # In which case, the index we are removing may have changed...
 132 
 133             # Find correct position.
 134             l.reverse() # Delete all the items, starting with the last item.
 135             for i in l:
 136                 pos = self.FindItem(i[0], i[2])
 137                 self.DeleteItem(pos)
 138 
 139 
 140     def Insert(self, x, y, seq):
 141         """
 142         Insert text at given x, y coordinates --- used with drag-and-drop.
 143         """
 144 
 145         # Find insertion point.
 146         index, flags = self.HitTest((x, y))
 147 
 148         if index == wx.NOT_FOUND: # Not clicked on an item.
 149             if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
 150                 index = self.GetItemCount() # Append to end of list.
 151             elif self.GetItemCount() > 0:
 152                 if y <= self.GetItemRect(0).y: # Clicked just above first item.
 153                     index = 0 # Append to top of list.
 154                 else:
 155                     index = self.GetItemCount() + 1 # Append to end of list.
 156         else: # Clicked on an item.
 157             # Get bounding rectangle for the item the user is dropping over.
 158             rect = self.GetItemRect(index)
 159 
 160             # If the user is dropping into the lower half of the rect,
 161             # we want to insert _after_ this item.
 162             # Correct for the fact that there may be a heading involved.
 163             if y > rect.y - self.GetItemRect(0).y + rect.height/2:
 164                 index += 1
 165 
 166         for i in seq: # Insert the item data.
 167             idx = self.InsertItem(index, i[2])
 168             self.SetItemData(idx, i[1])
 169             for j in range(1, self.GetColumnCount()):
 170                 try: # Target list can have more columns than source.
 171                     self.SetItem(idx, j, i[2+j])
 172                 except:
 173                     pass # Ignore the extra columns.
 174             index += 1
 175 
 176 #---------------------------------------------------------------------------
 177 
 178 class MyListDrop(wx.DropTarget):
 179     """
 180     Drop target for simple lists.
 181     """
 182     def __init__(self, source):
 183         """
 184         Arguments:
 185         source: source listctrl.
 186         """
 187         wx.DropTarget.__init__(self)
 188 
 189         #------------
 190         
 191         self.dv = source
 192 
 193         #------------
 194         
 195         # Specify the type of data we will accept.
 196         self.data = wx.CustomDataObject("ListCtrlItems")
 197         self.SetDataObject(self.data)
 198 
 199     #-----------------------------------------------------------------------
 200         
 201     # Called when OnDrop returns True.    
 202     # We need to get the data and do something with it.
 203     def OnData(self, x, y, d):
 204         """
 205         ...
 206         """
 207         
 208         # Copy the data from the drag source to our data object.
 209         if self.GetData():
 210             # Convert it back to a list and give it to the viewer.
 211             ldata = self.data.GetData()
 212             l = pickle.loads(ldata)
 213             self.dv.Insert(x, y, l)
 214 
 215         # What is returned signals the source what to do
 216         # with the original data (move, copy, etc.)  In this
 217         # case we just return the suggested value given to us.
 218         return d
 219 
 220 #---------------------------------------------------------------------------
 221 
 222 class MyApp(wx.App):    
 223     def OnInit(self):
 224 
 225         #------------
 226 
 227         frame = MyFrame(parent=None, id=-1)
 228         self.SetTopWindow(frame)
 229         frame.Show(True)
 230 
 231         return True
 232     
 233 #---------------------------------------------------------------------------
 234 
 235 def main():
 236     app = MyApp(False)
 237     app.MainLoop()
 238 
 239 #---------------------------------------------------------------------------
 240 
 241 if __name__ == "__main__" :
 242     main()


Sample two

img_sample_two.png

Toggle line numbers
   1 # sample_two.py


Download source

source.zip


Additional Information

Link :

https://wiki.wxpython.org/List%20control%20and%20SQLite%20database%20%28Phoenix%29

https://wiki.wxpython.org/List%20control%20virtual%20%28Phoenix%29

https://wiki.wxpython.org/List%20control%20virtual%20and%20SQLite%20database%20%28Phoenix%29

http://jak-o-shadows.users.sourceforge.net/python/wxpy/dblistctrl.html

http://wxpython-users.1045709.n5.nabble.com/Example-of-Database-Interaction-td2361801.html

http://www.kitebird.com/articles/pydbapi.html

https://dabodev.com/

https://www.pgadmin.org/download/

https://github.com/1966bc/pyggybank

https://sourceforge.net/projects/pyggybank/

- - - - -

https://wiki.wxpython.org/TitleIndex

https://docs.wxpython.org/


Thanks to

JohnFouhy (sample_one.py coding), ??? (sample_two.py coding) and the wxPython community...


About this page

Date(d/m/y) Person (bot) Comments :

14/03/20 - Ecco (Created page and updated examples for wxPython Phoenix).


Comments

- blah, blah, blah...

How to create a list control with drag and drop (Phoenix) (last edited 2020-12-13 14:08:37 by Ecco)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.