Differences between revisions 14 and 15
Revision 14 as of 2006-01-03 19:22:36
Size: 24402
Editor: ip54513330
Comment:
Revision 15 as of 2006-01-13 00:16:46
Size: 24426
Editor: j233174
Comment: app.frame.Layout() was forgotten in Drag and drop listctrl
Deletions are marked like this. Additions are marked like this.
Line 650: Line 650:
    app.frame.Layout()

List Controls

Basic operation

  • Associating python data with items

    Selecting and manipulating items in wxListCtrls (using SetItem* methods)

    Report-view List controls "why don't my items show up" (missing headers) self.list.InsertColumn( 0, "Items", width=-1)

See Also:

Associating Python Data with Items

When you need to associate data with an item:

Toggle line numbers
   1 listctrl.SetItemData( item_by_index, integer_for_item )

Yep! You get to associate a WHOLE integer with the item!

To associate more, make a num generator (or use wxNew`Id) and keep a dict binding id to whatever data you want to associate.

So, for example:

Toggle line numbers
   1 id = wxNewId()
   2 data_dict[ id ] = some_data_to_associate
   3 listctrl.InsertStringItem( index_to_place_at, string_name_of_item )
   4 listctrl.SetItemData( index_to_place_at, id )

So, now you can traverse:

index --> associated data (id) --> some_data_to_associate

Selecting Items Programmatically

To select an item programmatically in a wxListCtrl (Note that this appears to be a bug? Shouldn't need to use wxLIST_STATE_SELECTED for stateMask argument, should be able to use a MASK argument instead?):

  • self.SetItemState ( ID, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED  )

It should be (I think):

  • self.SetItemState( ID, wxLIST_STATE_SELECTED, wxLIST_MASK_STATE )

Note: I just tried both versions, and the first version works in wxPython 2.5; the second version (using LIST_MASK_STATE) does not.

I think only the first version is correct. The last parameter is a mask of all the states you want to modify, so it must consist only of wx.LIST_STATE_* combinations. The wx.LIST_MASK_STATE is only used in SetItem, where it tells which fields are valid. Seems the docs could be clearer though.

Retrieve Currently Selected Indices in List Control

A common task, there's no pre-built function to accomplish this, so here's a recipe:

Toggle line numbers
   1 def _getSelectedIndices( self, state =  wxLIST_STATE_SELECTED):
   2         indices = []
   3         found = 1
   4         lastFound = -1
   5         while found:
   6                 index = self.GetNextItem(
   7                         lastFound,
   8                         wxLIST_NEXT_ALL,
   9                         state,
  10                 )
  11                 if index == -1:
  12                         break
  13                 else:
  14                         lastFound = index
  15                         indices.append( index )
  16         return indices

wxListCtrl's Hello world

It took half an hour for a newbie like me to get this tiny application running. Until I saw that you must call "InsertStringItem" :-)

Toggle line numbers
   1 import wx
   2 class MyApp(wx.App):
   3     def OnInit(self):
   4         frame = wx.Frame(None, -1, "Hello from wxPython")
   5 
   6         id=wx.NewId()
   7         self.list=wx.ListCtrl(frame,id,style=wx.LC_REPORT|wx.SUNKEN_BORDER)
   8         self.list.Show(True)
   9 
  10         self.list.InsertColumn(0,"Data #1")
  11         self.list.InsertColumn(1,"Data #2")
  12         self.list.InsertColumn(2,"Data #3")
  13 
  14         self.list.InsertStringItem(0,"hello")
  15         self.list.SetStringItem(0,1,"world")
  16         self.list.SetStringItem(0,2,"!")
  17 
  18         frame.Show(True)
  19         self.SetTopWindow(frame)
  20         return True
  21 
  22 app = MyApp(0)
  23 app.MainLoop()

Changing fonts in a ListCtrl

Supposing you have a List Control, and you want to set some items to, say, bold. That's all - no changing anything else about the font, so the face remains the same as the other items. (Bear in mind the face will most likely be the default face as set by the system, and hence we don't know what it is.)

Because I (Dave Cridland) am terminally stupid, I didn't figure out how to do this, and couldn't find any documentation. In case anyone else is trying to do the same thing, and can't figure it out either, here's what I did:

Toggle line numbers
   1 import wx
   2 # I'm using the new namespace. Hoorah!
   3 
   4 # Note this is very much incomplete, and only dwells on how to set the font stuff in an attr.
   5 
   6 class FancyListCtrl( wx.ListCtrl ):
   7     def __init__( self, parent, id ):
   8         wx.ListCtrl.__init__( self, parent, id, style = wx.LC_REPORT|wx.LC_VIRTUAL )
   9         # We setup our pretty attribute once, here.
  10         self._funky_attr = wx.ListItemAttr()
  11         # This now contains default attributes.
  12         # We can set the text colour to be different:
  13         self._funky_attr.SetTextColour( wx.BLUE )
  14         # But we can't do either of:
  15         # self._funky_attr.GetFont().SetWeight( wx.BOLD )
  16         # (Above fails silently - probably GetFont() returns a copy.)
  17         # new_font = wx.Font()
  18         # (No default constructor in wxPython.)
  19         # But we can extract the default font:
  20         new_font = self._funky_attr.GetFont()
  21         # Set the weight on it:
  22         new_font.SetWeight( wx.BOLD )
  23         # Then put it back.
  24         self._funky_attr.SetFont( new_font )
  25         # self._funky_attr is now ready to be returned by OnGetItemAttr()
  26         # (since this happens to be virtual.)

Simply changing the font of a specific item:

Toggle line numbers
   1 # Get the item at a specific index:
   2 item = self.myListControl.GetItem(index)
   3 # Get its font, change it, and put it back:
   4 font = item.GetFont()
   5 font.SetWeight(wx.FONTWEIGHT_BOLD)
   6 item.SetFont(font)
   7 # This does the trick:
   8 self.myListControl.SetItem(item)

Unselecting an item programmatically

It took me (Werner Bruhin) some searching, as always when one figures it out it is easy!

Toggle line numbers
   1 # selecting as shown in the demo
   2 self.SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED)
   3 
   4 # unselecting
   5 self.SetItemState(item, 0, wxLIST_STATE_SELECTED)

Type Ahead Mixin

Windows (and presumably other OS do as well) provides Type Ahead functionality by default in list controls. But not if they are Virtual. I had a need to provide Type Ahead for some virtual controls in my app, so I knocked up this Mixin class for wxListCtrl objects. Happily it works with both Virtual and Normal list controls which means if you use it in your app then all your list controls can have the same Type Ahead behaviour.

There are some things I've tried to make configurable; the type ahead timeout, case sensitivity to the search, special keycodes to avoid during typeahead, and I've provided methods that you could override to change the default behaviour that I've coded (it was almost on a whim as I didn't really like the behaviour that Windows was providing, it seemed, weird). To help understand what's going on I've tried to document the code to explain the bits I think are weird.

One thing that is notable is that the default windows type ahead doesn't seem to recognise the space character, with some playing about with EVT_KEY_DOWN and EVT_CHAR events I've made my type ahead deal with spaces. Which is nice.

Anyway, on with the code (please excuse the verbosity of my variable and method names :) ).

Toggle line numbers
   1 from wxPython.wx import *
   2 
   3 class TypeAheadListCtrlMixin:
   4     """  A Mixin Class that does type ahead scrolling for list controls.
   5          Assumes that the wxListCtrl it is mixed into is sorted (it's using
   6          a binary search to find the correct item).
   7 
   8          I wrote this because on Windows there was no type ahead when you
   9          used a virtual list control, and then couldn't be bohered deciphering
  10          the default windows typeahead for non-virtual list controls.  So I
  11          made it work for both virtual and non-virtual controls so that all
  12          my list controls would have the same functionality.
  13 
  14          Things you can change programatically:
  15          * expand or contract the list of keycodes that stop the type ahead
  16          * expand or contract the list of keycodes that are allowed to be
  17            used inside typeahead, but won't start it (e.g. space which normally
  18            acts as an Activation Key)
  19          * change the timeout time (init param, defaults to 500 milliseconds)
  20          * change the sensitivity of the search (init param, defaults to caseinsensitive)
  21          Things you can change in the class that you mix this into:
  22          * override the following methods:
  23            - currentlySelectedItemFoundByTypeAhead
  24            - currentlySelectedItemNotFoundByTypeAhead
  25            - newItemFoundByTypeAhead
  26            - nothingFoundByTypeAhead
  27            changing these changes the behaviour of the typeahead in various stages.
  28            See doc comments on methods.
  29 
  30         Written by Murray Steele (muz at h-lame dot com)
  31     """
  32 
  33     # These Keycodes are the ones that if we detect them we will cancel the current
  34     # typeahead state.
  35     stopTypeAheadKeyCodes = [
  36      WXK_BACK,
  37      WXK_TAB,
  38      WXK_RETURN,
  39      WXK_ESCAPE,
  40      WXK_DELETE,
  41      WXK_START,
  42      WXK_LBUTTON,
  43      WXK_RBUTTON,
  44      WXK_CANCEL,
  45      WXK_MBUTTON,
  46      WXK_CLEAR,
  47      WXK_PAUSE,
  48      WXK_CAPITAL,
  49      WXK_PRIOR,
  50      WXK_NEXT,
  51      WXK_END,
  52      WXK_HOME,
  53      WXK_LEFT,
  54      WXK_UP,
  55      WXK_RIGHT,
  56      WXK_DOWN,
  57      WXK_SELECT,
  58      WXK_PRINT,
  59      WXK_EXECUTE,
  60      WXK_SNAPSHOT,
  61      WXK_INSERT,
  62      WXK_HELP,
  63      WXK_F1,
  64      WXK_F2,
  65      WXK_F3,
  66      WXK_F4,
  67      WXK_F5,
  68      WXK_F6,
  69      WXK_F7,
  70      WXK_F8,
  71      WXK_F9,
  72      WXK_F10,
  73      WXK_F11,
  74      WXK_F12,
  75      WXK_F13,
  76      WXK_F14,
  77      WXK_F15,
  78      WXK_F16,
  79      WXK_F17,
  80      WXK_F18,
  81      WXK_F19,
  82      WXK_F20,
  83      WXK_F21,
  84      WXK_F22,
  85      WXK_F23,
  86      WXK_F24,
  87      WXK_NUMLOCK,
  88      WXK_SCROLL]
  89     # These are the keycodes that we have to catch in evt_key_down, not evt_char
  90     # By the time they get to evt_char then the OS has looked at them and gone,
  91     # hey, this keypress means do something (like pressing space acts as an ACTIVATE
  92     # key in a list control.
  93     catchInKeyDownIfDuringTypeAheadKeyCodes = [
  94      WXK_SPACE
  95     ]
  96     # These are the keycodes that we will allow during typeahead, but won't allow to start
  97     # the type ahead process.
  98     dontStartTypeAheadKeyCodes = [
  99      WXK_SHIFT,
 100      WXK_CONTROL,
 101      WXK_MENU #ALT Key, ALT Gr generates both WXK_CONTROL and WXK_MENU.
 102      ]
 103     dontStartTypeAheadKeyCodes.extend(catchInKeyDownIfDuringTypeAheadKeyCodes)
 104 
 105     def __init__(self, typeAheadTimeout = 500, casesensitive = False, columnToSearch = 0):
 106         # Do most work in the char handler instead of keydown.
 107         # This means we get the correct keycode for the key pressed as it should
 108         # appear on screen, rather than all uppercase or "default" us keyboard
 109         # punctuation.
 110         # However there are things that we need to catch in key_down to stop
 111         # them getting sent to the underlying windows control and generating
 112         # other events (notably I'm talking about the SPACE key which generates
 113         # an ACTIVATE event in these list controls).
 114         EVT_KEY_DOWN(self, self.OnTypeAheadKeyDown)
 115         EVT_CHAR(self, self.OnTypeAheadChar)
 116         timerId = wxNewId()
 117         self.typeAheadTimer = wxTimer(self,timerId)
 118         EVT_TIMER(self,timerId,self.OnTypeAheadTimer)
 119         self.clearTypeAhead()
 120         self.typeAheadTimeout = typeAheadTimeout
 121         self.columnToSearch = columnToSearch
 122         if not casesensitive:
 123             self._GetItemText = lambda idx: self.GetItem(idx,self.columnToSearch).GetText().lower()
 124             self._GetKeyCode = lambda keycode: chr(keycode).lower()
 125         else:
 126             self._GetItemText = lambda idx: self.GetItem(idx,self.columnToSearch).GetText()
 127             self._GetKeyCode = chr
 128 
 129     def OnTypeAheadKeyDown(self, event):
 130         keycode = event.GetKeyCode()
 131         if keycode in self.stopTypeAheadKeyCodes:
 132             self.clearTypeAhead()
 133         else:
 134             if self.typeAhead == None:
 135                 if keycode in self.dontStartTypeAheadKeyCodes:
 136                     self.clearTypeAhead()
 137             else:
 138                 if keycode in self.catchInKeyDownIfDuringTypeAheadKeyCodes:
 139                     self.OnTypeAheadChar(event)
 140                     return
 141         event.Skip()
 142 
 143     def OnTypeAheadChar(self, event):
 144         # stop the timer, to make sure that it doesn't fire in the middle of
 145         # doing this and screw up by None-ifying the typeAhead string.
 146         # TODO: Yes some kind of lock around a typeAheadState object
 147         # that contained typeAhead, lastTypeAheadFoundAnything and lastTypeAhead
 148         # would be better...
 149         self.typeAheadTimer.Stop()
 150         keycode = event.GetKeyCode()
 151         if keycode in self.stopTypeAheadKeyCodes:
 152             self.clearTypeAhead()
 153             event.Skip()
 154             return
 155         else:
 156             if self.typeAhead == None:
 157                 if keycode in self.dontStartTypeAheadKeyCodes:
 158                     self.clearTypeAhead()
 159                     event.Skip()
 160                     return
 161                 else:
 162                     self.typeAhead = self._GetKeyCode(keycode)
 163             else:
 164                 self.typeAhead += self._GetKeyCode(keycode)
 165             self.doTypeAhead()
 166             # This timer is used to nullify the typeahead after a while
 167             self.typeAheadTimer.Start(self.typeAheadTimeout,wxTIMER_ONE_SHOT)
 168 
 169     def inTypeAhead(self):
 170         return self.typeAhead != None
 171 
 172     def currentlySelectedItemFoundByTypeAhead(self, idx):
 173         """This method is called when the typeahead string matches
 174            the text of the currently selected item.  Put code here if
 175            you want to have something happen in this case.
 176            NOTE: Method only called if there was a currently selected item.
 177 
 178            idx refers to the index of the currently selected item."""
 179         # we don't do anything as we've already selected the thing we want
 180         pass
 181 
 182     def currentlySelectedItemNotFoundByTypeAhead(self, idx):
 183         """This method is called when the typeahead string matches
 184            an item that isn't the currently selected one.  Put code
 185            here if you want something to happen to the currently
 186            selected item.
 187            NOTE: use newItemFoundByTypeAhead for doing something to
 188            the newly matched item.
 189            NOTE: Method only called if there was a currently selected item.
 190 
 191            idx referes to the index of the currently selected item."""
 192         # we deselect it.
 193         self.SetItemState(idx, 0, wxLIST_STATE_SELECTED)
 194         self.SetItemState(idx, 0, wxLIST_STATE_FOCUSED)
 195 
 196     def newItemFoundByTypeAhead(self, idx):
 197         """This is called when the typeahead string matches
 198            an item that isn't the currently selected one.  Put
 199            code here if you want something to happen to the newly
 200            found item.
 201            NOTE: use currentlySelectedItemNotFoundByTypeAhead for
 202            doing something to the previously selected item.
 203 
 204            idx refers to the index of the newly matched item."""
 205         # we select it and make sure it is focused
 206         self.SetItemState(idx, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED)
 207         self.SetItemState(idx, wxLIST_STATE_FOCUSED, wxLIST_STATE_FOCUSED)
 208         self.EnsureVisible(idx)
 209 
 210     def nothingFoundByTypeAhead(self, idx):
 211         """This method is called when the typeahead string doesn't
 212            match any items.  Put code here if you want something to
 213            happen in this case.
 214 
 215            idx refers to the index of the currently selected item
 216            or -1 if nothing was selected."""
 217         # don't do anything here, what could we do?
 218         pass
 219 
 220     def doTypeAhead(self):
 221         curselected = -1
 222         if self.lastTypeAheadFoundSomething:
 223             curselected = self.lastTypeAhead
 224         else:
 225             curselected = self.GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED)
 226         min = 0
 227         if curselected != -1:
 228             term_name = self._GetItemText(curselected)
 229             if term_name.startswith(self.typeAhead):
 230                 self.currentlySelectedItemFoundByTypeAhead(curselected)
 231                 self.lastTypeAheadFoundAnything = True
 232                 self.lastTypeAhead = curselected
 233                 return #We don't want this edgecase falling through
 234 
 235         new_idx = self.binary_search(self.typeAhead,min)
 236         if new_idx != -1:
 237             if new_idx != curselected and curselected != -1:
 238                 self.currentlySelectedItemNotFoundByTypeAhead(curselected)
 239             self.newItemFoundByTypeAhead(new_idx)
 240             self.lastTypeAheadFoundAnything = True
 241             self.lastTypeAhead = new_idx
 242         else:
 243             self.nothingFoundByTypeAhead(curselected)
 244             self.lastTypeAheadFoundAnything = False
 245             self.lastTypeAhead = -1
 246 
 247     # NOTE: Originally from ASPN. Augmented.
 248     def binary_search(self, t, min = 0):
 249         min = min;
 250         max = self.GetItemCount() - 1
 251         while 1:
 252             if max < min:
 253                 return self.doEdgeCase(m, t)
 254             m = (min + max) / 2
 255             cur_term = self._GetItemText(m)
 256             if cur_term < t:
 257                 min = m + 1
 258             elif cur_term > t:
 259                 max = m - 1
 260             else:
 261                 return m
 262 
 263     def doEdgeCase(self, m, t):
 264         """ This method makes sure that if we don't find the typeahead
 265          as an actual string, then we will return the first item
 266          that starts with the typeahead string (if there is one)"""
 267         before = self._GetItemText(max(0,m-1))
 268         this = self._GetItemText(m)
 269         after = self._GetItemText(min((self.GetItemCount()-1),m+1))
 270         slice = len(t)
 271         if this[:slice] == t:
 272             return m
 273         elif before[:slice] == t:
 274             return max(0,m-1)
 275         elif after[:slice] == t:
 276             return min((self.GetItemCount()-1),m+1)
 277         else:
 278             return -1
 279 
 280     def clearTypeAhead(self):
 281         self.typeAhead = None
 282         self.lastTypeAheadFoundSomething = False
 283         self.lastTypeAheadIdx = -1
 284 
 285     def OnTypeAheadTimer(self, event):
 286         self.clearTypeAhead()

Customizing ColumnSorterMixin to Sort Dates

This code augments wx.lib.mixins.listctrl.ColumnSorterMixin so that it can sort dates that match the date_re regular expression listed at the top of the code. You need to modify another section of the code to transform your date into the YYYYMMDD format so that the dates can be easily sorted numerically. Alternatively, you could use the datetime module and store and sort date objects.

Toggle line numbers
   1 import wx
   2 import wx.lib.mixins.listctrl
   3 import locale
   4 import re
   5 
   6 # Change this to your settings
   7 date_re = re.compile("(\d\d-\d\d-\d\d\d\d)")
   8 
   9 #----------------------------------------------------------------------------
  10 
  11 class CustColumnSorterMixin(wx.lib.mixins.listctrl.ColumnSorterMixin):
  12     def __init__(self, numColumns):
  13         wx.lib.mixins.listctrl.ColumnSorterMixin(self, numColumns)
  14 
  15     def GetColumnSorter(self):
  16         return self.CustColumnSorter
  17 
  18     def CustColumnSorter(self, key1, key2):
  19         col = self._col
  20         ascending = self._colSortFlag[col]
  21         item1 = self.itemDataMap[key1][col]
  22         item2 = self.itemDataMap[key2][col]
  23 
  24         alpha = date_re.match(item1)
  25         beta =  date_re.match(item2)
  26         if None != alpha and None != beta:
  27             a = alpha.groups(1)[0]
  28             b =  beta.groups(1)[0]
  29             # Change these from your settings to YYYYMMDD
  30             item1 = a[-4:]+a[:2]+a[3:5]
  31             item2 = b[-4:]+b[:2]+b[3:5]
  32 
  33             item1 = int(item1)
  34             item2 = int(item2)
  35 
  36         #--- Internationalization of string sorting with locale module
  37         if type(item1) == type('') or type(item2) == type(''):
  38             cmpVal = locale.strcoll(str(item1), str(item2))
  39         else:
  40             cmpVal = cmp(item1, item2)
  41         #---
  42 
  43         # If the items are equal then pick something else to make the sort value unique
  44         if cmpVal == 0:
  45             cmpVal = apply(cmp, self.GetSecondarySortValues(col, key1, key2))
  46 
  47         if ascending:
  48             return cmpVal
  49         else:
  50             return -cmpVal

Drag and Drop with lists

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! - JohnFouhy

Toggle line numbers
   1 """ DnD demo with listctrl. """
   2 
   3 import wx
   4 import string
   5 
   6 class DragList(wx.ListCtrl):
   7     def __init__(self, parent, **kw):
   8         kw['style'] = wx.LC_SINGLE_SEL|wx.LC_LIST
   9         wx.ListCtrl.__init__(self, parent, **kw)
  10 
  11         self.Bind(wx.EVT_LIST_BEGIN_DRAG, self._startDrag)
  12 
  13         dt = ListDrop(self._insert)
  14         self.SetDropTarget(dt)
  15 
  16     def _startDrag(self, e):
  17         """ Put together a data object for drag-and-drop _from_ this list. """
  18 
  19         # Create the data object: Just use plain text.
  20         data = wx.PyTextDataObject()
  21         idx = e.GetIndex()
  22         text = self.GetItem(idx).GetText()
  23         data.SetText(text)
  24 
  25         # Create drop source and begin drag-and-drop.
  26         dropSource = wx.DropSource(self)
  27         dropSource.SetData(data)
  28         res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
  29 
  30         # If move, we want to remove the item from this list.
  31         if res == wx.DragMove:
  32             # It's possible we are dragging/dropping from this list to this list.  In which case, the
  33             # index we are removing may have changed...
  34             
  35             # Find correct position.
  36             pos = self.FindItem(idx, text)
  37             self.DeleteItem(pos)
  38 
  39     def _insert(self, x, y, text):
  40         """ Insert text at given x, y coordinates --- used with drag-and-drop. """
  41 
  42         # Clean text.
  43         text = filter(lambda x: x in (string.letters + string.digits + string.punctuation + ' '), text)
  44 
  45         # Find insertion point.
  46         index, flags = self.HitTest((x, y))
  47 
  48         if index == wx.NOT_FOUND:
  49             if flags & wx.LIST_HITTEST_NOWHERE:
  50                 index = self.GetItemCount()
  51             else:
  52                 return
  53         
  54         # Get bounding rectangle for the item the user is dropping over.
  55         rect = self.GetItemRect(index)
  56 
  57         # If the user is dropping into the lower half of the rect, we want to insert _after_ this item.
  58         if y > (rect.y + rect.height/2):
  59             index = index + 1
  60 
  61         self.InsertStringItem(index, text)
  62 
  63 class ListDrop(wx.PyDropTarget):
  64     """ Drop target for simple lists. """
  65 
  66     def __init__(self, setFn):
  67         """ Arguments:
  68          - setFn: Function to call on drop.
  69         """
  70         wx.PyDropTarget.__init__(self)
  71 
  72         self.setFn = setFn
  73 
  74         # specify the type of data we will accept
  75         self.data = wx.PyTextDataObject()
  76         self.SetDataObject(self.data)
  77 
  78     # Called when OnDrop returns True.  We need to get the data and
  79     # do something with it.
  80     def OnData(self, x, y, d):
  81         # copy the data from the drag source to our data object
  82         if self.GetData():
  83             self.setFn(x, y, self.data.GetText())
  84             
  85         # what is returned signals the source what to do
  86         # with the original data (move, copy, etc.)  In this
  87         # case we just return the suggested value given to us.
  88         return d  
  89 
  90 if __name__ == '__main__':
  91     items = ['Foo', 'Bar', 'Baz', 'Zif', 'Zaf', 'Zof']
  92 
  93     class MyApp(wx.App):
  94         def OnInit(self):
  95             self.frame = wx.Frame(None, title='Main Frame')
  96             self.frame.Show(True)
  97             self.SetTopWindow(self.frame)
  98             return True
  99 
 100     app = MyApp(redirect=False)
 101     dl1 = DragList(app.frame)
 102     dl2 = DragList(app.frame)
 103     sizer = wx.BoxSizer()
 104     app.frame.SetSizer(sizer)
 105     sizer.Add(dl1, proportion=1, flag=wx.EXPAND)
 106     sizer.Add(dl2, proportion=1, flag=wx.EXPAND)
 107     for item in items:
 108         dl1.InsertStringItem(99, item)
 109         dl2.InsertStringItem(99, item)
 110     app.frame.Layout()
 111     app.MainLoop()

The content on this page came from ListAndTreeControls, which was split up into this page and TreeControls .

How to create a list control (info) (last edited 2020-12-13 13:46:55 by Ecco)

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