[wxPython-users] Re: Find a component by name or ID ?

Bob Klahn bobstones at comcast.net
Fri Oct 26 14:15:37 PDT 2007


Hi Larry,

I'm mystified!  This is the first I've seen wx.FindWindowByLabel 
fail.  Sure looks like a wxPython or wxWidgets bug to me.  Robin??

As a work-around, you can of course make your STFD a global 
variable.  But that's hardly satisfying.

Bob

At 03:09 PM 10/26/2007, Larry Bates wrote:
>Bob Klahn wrote:
>>Did you first use SetLabel, Larry?  You need to do that.  If you 
>>did that, are you sure you're trying to find the same label you've set?
>>Got a small coding example of what's not working for you?
>>Bob
>>At 06:32 PM 10/25/2007, Larry Bates wrote:
>>>Bob Klahn wrote:
>>>>At 02:10 PM 10/21/2007, Stef Mientki wrote:
>>>>So the questions are:
>>>>>How can I find a component by it's ID (annd limit the search to 
>>>>>a specified parent) ?
>>>>>How can I find a wx-component, in a specified parent/container, 
>>>>>by it's name ?
>>>>Stef, I find windows by label, and I find that extremely 
>>>>handy.  I simply use .SetLabel('the label') on the windows I need to find, and
>>>>wx.FindWindowByLabel('the label') elsewhere.
>>>>And wx.FindWindowByLabel has a second, optional argument, the 
>>>>"parent"; if present, the search will be limited, as the help 
>>>>text states,  to the given window hierarchy.
>>>>The labels I create reflect the hierarchy of my =data=; the 
>>>>window hierarchy can be completely different.  As needs arise for 
>>>>me to change my applications' layouts, I rarely need to change 
>>>>anything relating to data access.    But you know all that, 
>>>>having used this kind of technique in Delphi.
>>>>FindWindowById and FindWindowByName also exist, and they too 
>>>>carry the second optional argument.  But, for me at least, 
>>>>finding by label is by far the most flexible.  (BTW, 
>>>>FindWindowByName will call FindWindowByLabel if the searched-for 
>>>>name is not found.)
>>>>Bob
>>>>P.S.  I'm curious: how come you switched from Delphi to wxWindows?
>>>>I'm guessing it was primarily a financial decision.
>>>
>>>Bob,
>>>
>>>I have something REALLY odd happening when I try this.  I can 
>>>FindWindowByLabel in one class, but it returns None in another class.
>>>I copied the code from one to another so I know it is the same.  I 
>>>have a single top-level frame (which is what I'm trying to get 
>>>access to).  This seems like it would be so easy.  Any ideas?
>>>
>>>Thanks in advance.
>>>Larry
>
>Absolutely sure that I did a set label (the FindWindowByLabel works in one
>place).  Then when I try to do it down inside a callback class for 
>showing progress on a gauge in my custom status bar it can't find it 
>(returns None).
>
>I've stripped it down to a minimal application and attached to this 
>message if you want to take a look.
>
>-Larry
>
>
>import sys
>import os
>import wx
>from wx.lib.mixins import treemixin
>import wx.lib.mixins.listctrl as listmix
>#
># Define wsAPI Callback class
>#
>class Callback(object):
>     '''
>     Callback class used to display progress during uploads
>     '''
>     def __init__(self, gauge):
>         self.gauge=gauge
>         self.gauge.Show(True)
>         self.__call__=self.progress
>         self.frame=wx.FindWindowByLabel('WSuploadFrame')
>         print "Callback.__init__-frame=", self.frame
>         return
>
>     def start(self, total):
>         '''
>         This gets called at the beginning of the upload
>         '''
>         self.total=total
>         self.gauge.SetRange(total)
>         #
>         # Make sure last cancel is cleared
>         #
>         self.gauge.continueFlag=True
>         return self.gauge.continueFlag
>
>     def progress(self, total, position):
>         '''
>         This gets called multiple times during the upload every time
>         a block is uploaded.
>         '''
>         self.gauge.SetValue(position)
>         pctdone=100*int(float(position)/total)
>         suffix=" (%i%%)" % pctdone
>         self.frame.SetFrameTitle(self.frame.appTitle, suffix=suffix)
>         wx.Yield()
>         return self.gauge.continueFlag
>
>     def complete(self):
>         '''
>         This gets called at the end of the upload
>         '''
>         self.gauge.SetValue(self.total)
>         self.gauge.Show(False)
>         self.frame.SetTitle(self.frame.appTitle)
>         return True
>
>class usernameComboBox(wx.ComboBox):
>     '''
>     usernameComboBox - This class handles the From: combo box
>     '''
>     def __init__(self, parent, *args, **kwds):
>         wx.ComboBox.__init__(self, parent, *args, **kwds)
>         self.frame=wx.FindWindowByLabel('WSuploadFrame')
>         print "usernameComboBox.__init__-frame=", self.frame
>
>class sendToTreeCtrl(treemixin.VirtualTree, treemixin.TreeHelper, 
>wx.TreeCtrl):
>     def __init__(self, parent, *args, **kwds):
>         super(sendToTreeCtrl, self).__init__(parent, *args, **kwds)
>         self.frame=wx.FindWindowByLabel('WSuploadFrame')
>         print "sendToTreeCtrl.__init__-frame=", self.frame
>
>class makeNewFolderTextCtrl(wx.TextCtrl):
>     def __init__(self, parent, *args, **kwds):
>         wx.TextCtrl.__init__(self, parent, *args, **kwds)
>         self.frame=wx.FindWindowByLabel('WSuploadFrame')
>         print "makeNewFolderTextCtrl.__init__-frame=", self.frame
>
>class filenamesListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
>     def __init__(self, parent, *args, **kwds):
>         wx.ListCtrl.__init__(self, parent, *args, **kwds)
>         listmix.ListCtrlAutoWidthMixin.__init__(self)
>         self.itemDataMap={}
>##        #
>##        # Insert 2 columns in the filenames list (filename, size)
>##        #
>##        self.InsertColumn(0, 'Filename', width=350)
>##        self.InsertColumn(1, 'Size', format=wx.LIST_FORMAT_RIGHT)
>
>
>     def GetListCtrl(self):
>         '''
>         GetListCtrl - this method is used by the ColumnSorterMixin
>         '''
>         return self
>
>
>class fileDropTarget(wx.FileDropTarget):
>     '''
>     fileDropTarget - class that implements a fileDropTarget object for the
>                      filenames list control.  Allows user to 
> drag-n-drop files
>                      on to the filenames list control.
>     '''
>     def __init__(self, parent, *args, **kwds):
>         wx.FileDropTarget.__init__(self, *args, **kwds)
>         self.frame=wx.FindWindowByLabel('WSuploadFrame')
>         print "fileDropTarget.__init__-frame=", self.frame
>
>class customStatusBar(wx.StatusBar):
>     def __init__(self, parent, *args, **kwds):
>         wx.StatusBar.__init__(self, parent, *args, **kwds)
>         self.SetFieldsCount(2)
>         self.SetStatusWidths([-1, 120])
>         self.sizeChanged = False
>         self.Bind(wx.EVT_SIZE, self.OnSize)
>         self.Bind(wx.EVT_IDLE, self.OnIdle)
>
>         #
>         # Put progress gauge in field 1 (the second field)
>         #
>         self.gauge = wx.Gauge(self, -1, size=(-1, -1),
>                               style=wx.GA_HORIZONTAL)
>
>         self.gauge.Hide()
>         self.Reposition()
>         self.frame=wx.FindWindowByLabel('WSuploadFrame')
>         print "customStatusBar.__init__-frame=", self.frame
>
>     def Reposition(self):
>         #
>         # Get coordinates of the second field on the statusbar
>         #
>         rect = self.GetFieldRect(1)
>         #
>         # position the gauge
>         #
>         self.gauge.SetPosition((rect.x+2, rect.y+5))
>         self.gauge.SetSize((rect.width-4, 10))
>         self.Update()
>         self.sizeChanged = False
>
>     def OnSize(self, event):
>         self.Reposition()  # for normal size events
>
>         # Set a flag so the idle time handler will also do the repositioning.
>         # It is done this way to get around a buglet where 
> GetFieldRect is not
>         # accurate during the EVT_SIZE resulting from a frame maximize.
>         self.sizeChanged = True
>
>     def OnIdle(self, event):
>         if self.sizeChanged:
>             self.Reposition()
>
>
>     def onCancelUpload(self, event):
>         self.gauge.continueFlag=False
>
>
>class WSuploadFrame(wx.Frame):
>     def __init__(self, *args, **kwds):
>         wx.Frame.__init__(self, *args, **kwds)
>         self.SetLabel('WSuploadFrame')
>
>         # -----From: Combo box 
> ------------------------------------------------
>         self.label_from = wx.StaticText(self, -1, "Username:")
>
>         self.UCB=usernameComboBox(self, -1, style=wx.CB_DROPDOWN |
>                                                   wx.CB_SORT |
>                                                   wx.TE_PROCESS_ENTER)
>
>         # ----- WebSafe TreeCtrl 
> ----------------------------------------------
>         self.panel_1 = wx.Panel(self, -1)
>         self.panel_1.SetMinSize((-1, 200))
>         txt= "Choose a WebSafe Folder (gray folders are read-only):"
>         self.label_1 = wx.StaticText(self, -1, txt)
>         self.STTC = sendToTreeCtrl(self.panel_1, -1,
>                                    style=wx.TR_HAS_BUTTONS|
>                                          wx.TR_LINES_AT_ROOT|
>                                          wx.TR_HIDE_ROOT|
>                                          wx.TR_DEFAULT_STYLE|
>                                          wx.SUNKEN_BORDER)
>
>         # ----- Make New Folder TextCtrl 
> --------------------------------------
>         txt="Folder:"
>         self.label_2 = wx.StaticText(self, -1, txt)
>         self.FTC = makeNewFolderTextCtrl(self, -1, "",
>                                          style=wx.TE_PROCESS_ENTER|
>                                                wx.TE_PROCESS_TAB)
>
>         self.makeNewFolderBtn = wx.Button(self, -1, "&Make New Folder")
>         self.makeNewFolderBtn.Enable(False)
>
>         # -----Filenames list control 
> -----------------------------------------
>         msg="Files to be uploaded:"
>         self.sizer_filenames_staticbox = wx.StaticBox(self, -1, msg)
>         self.FLC=filenamesListCtrl(self, -1, style=wx.LC_REPORT|
>                                                    wx.SUNKEN_BORDER|
>                                                    wx.LC_HRULES |
>                                                    wx.LC_VRULES)
>
>         self.FLC.SetMinSize((400, 200))
>         self.fileDropTarget=fileDropTarget(self)
>         self.FLC.SetDropTarget(self.fileDropTarget)
>         # -----Buttons 
> --------------------------------------------------------
>         self.uploadBtn = wx.Button(self, -1, "Upload")
>         self.cancelBtn = wx.Button(self, wx.ID_CANCEL, "")
>         # -----Custom 
> StatusBar------------------------------------------------
>         # Start with a single field and split into two fields during uploads
>         #
>         self.CSB=customStatusBar(self)
>         self.SetStatusBar(self.CSB)
>         self.__set_properties()
>         self.__do_layout()
>         self.Bind(wx.EVT_BUTTON, self.onUpload, self.uploadBtn)
>
>
>     def __set_properties(self):
>         self.appTitle="WebSafe Tools Upload"
>         self.setFrameTitle(self.appTitle)
>         frameSize=(560, -1)
>         self.SetSize(frameSize)
>         self.SetMinSize(frameSize)
>         bgc=wx.SystemSettings_GetColour(wx.SYS_COLOUR_MENUBAR)
>         self.SetBackgroundColour(bgc)
>
>     def __do_layout(self):
>         # begin wxGlade: WSupdate.__do_layout
>         grid_sizer_DLG = wx.FlexGridSizer(5, 1, 0, 0)
>         grid_sizer_DLG.AddGrowableCol(0)
>         grid_sizer_DLG.AddGrowableRow(2) # Folders TreeCtrl
>         grid_sizer_DLG.AddGrowableRow(6) # Files ListCtrl
>
>         #sizer_from = wx.BoxSizer(wx.HORIZONTAL)
>         #
>         # From ComboBox
>         #
>         grid_sizer_FCB = wx.FlexGridSizer(1, 2, 0, 0)
>         grid_sizer_FCB.Add(self.label_from, 0, wx.RIGHT |
>                                                wx.ALIGN_CENTER_VERTICAL |
>                                                wx.LEFT, 10)
>
>         grid_sizer_FCB.Add(self.UCB, 0, wx.EXPAND, 0)
>         grid_sizer_FCB.AddGrowableCol(1)
>         grid_sizer_DLG.Add(grid_sizer_FCB, 1, wx.LEFT |
>                                               wx.RIGHT |
>                                               wx.TOP |
>                                               wx.EXPAND, 10)
>         #
>         # TreeControl
>         #
>         grid_sizer_DLG.Add(self.label_1, 0, wx.ALL, 10)
>         sizer_STTC = wx.BoxSizer(wx.HORIZONTAL)
>         sizer_STTC.Add(self.STTC, 1, wx.EXPAND)
>         self.panel_1.SetSizer(sizer_STTC)
>         grid_sizer_DLG.Add(self.panel_1, 1, wx.LEFT|
>                                             wx.RIGHT|
>                                             wx.BOTTOM|
>                                             wx.EXPAND, 10)
>
>         #
>         # Make New Folder TextControl
>         #
>         grid_sizer_FTC = wx.FlexGridSizer(1, 2, 0, 0)
>         grid_sizer_FTC.Add(self.label_2, 0, wx.RIGHT|
>                                             wx.ALIGN_CENTER_VERTICAL, 5)
>
>         grid_sizer_FTC.Add(self.FTC, 0, wx.EXPAND, 0)
>         grid_sizer_FTC.AddGrowableCol(1)
>         grid_sizer_DLG.Add(grid_sizer_FTC, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)
>         #
>         # Buttons
>         #
>         grid_sizer_BTNS = wx.FlexGridSizer(1, 3, 0, 0)
>         grid_sizer_BTNS.Add(self.makeNewFolderBtn, 0, 0, 0)
>         grid_sizer_BTNS.Add((20, 20), 0, 0, 0)
>         sizer_OkCancel = wx.BoxSizer(wx.HORIZONTAL)
>         sizer_OkCancel.Add(self.uploadBtn, 0, 0, 0)
>         sizer_OkCancel.Add((8, 20), 0, 0, 0)
>         sizer_OkCancel.Add(self.cancelBtn, 0, 0, 0)
>         grid_sizer_BTNS.Add(sizer_OkCancel, 1, wx.EXPAND, 0)
>         grid_sizer_BTNS.AddGrowableCol(1)
>         grid_sizer_DLG.Add(grid_sizer_BTNS, 1, wx.ALL|wx.EXPAND, 10)
>
>         #
>         # Filenames ListControl
>         #
>         sizer_filenames = wx.StaticBoxSizer(self.sizer_filenames_staticbox,
>                                             wx.HORIZONTAL)
>         sizer_filenames.Add(self.FLC, 1, wx.EXPAND, 0)
>         grid_sizer_DLG.Add(sizer_filenames, 1, wx.EXPAND, 0)
>
>         self.SetSizer(grid_sizer_DLG)
>         grid_sizer_DLG.Fit(self)
>
>         self.Layout()
>
>     def setFrameTitle(self, title, suffix=''):
>         self.SetTitle(title+suffix)
>
>     def onUpload(self, event):
>         CB=Callback(self.CSB.gauge)
>
>
>app = wx.PySimpleApp(0)
>wx.InitAllImageHandlers()
>#
># Create top folder instance
>#
>STFD = WSuploadFrame(None, -1, "")
>STFD.Show()
>app.SetTopWindow(STFD)
>app.MainLoop()






More information about the wxpython-users mailing list