[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