Can I create a Button Control Array?

Basically what I want is 2 x 16 Grid of buttons that I can use a
single EVT_ and an index to decide which of the buttons was Clicked
on.

Even better would be an EVT_ for the right side of 16 buttons and an
EVT_ for left side of 8 buttons...

Is this possible in wxPython?

Sure.

Depending on how uniform the buttons' properties are, you can probably
get away with creating 16 of them in a loop and then doing that a
second time for the other 8. (Since you suggested there was a
difference between the right and left.

You could do something like:

1) Make two lists of button names (the label on the button).

2) Loop through these lists, like so (adjust code appropriately)--here
just the 16 first:

for button_name in list_of_16_button_names:
    button = wx.Button(self.the_panel_it_is_on, button_name, etc....)
    button.Bind(wx.EVT_BUTTON, self.OnButtonPressed)

then do it again for the other 8, maybe binding to a different event handler.

3) In the event handler you can get which button the event came from.

def OnButtonPressed(self,event):
     button_pressed = event.GetEventObject()

At that point you might have some kind of dictionary or something that
tells you what to do based on which button was pressed. You could use
the label as the key, and you'd get the label by continuing in (3)....

    label = button_pressed.GetLabel()

Che

···

On Wed, Sep 7, 2011 at 11:07 AM, SpiritualMadMan <madrucke@yahoo.com> wrote:

Basically what I want is 2 x 16 Grid of buttons that I can use a
single EVT_ and an index to decide which of the buttons was Clicked
on.

Even better would be an EVT_ for the right side of 16 buttons and an
EVT_ for left side of 8 buttons...

Is this possible in wxPython?

Absolutely. wxButtons have (at least) two properties that lend themselves to this approach: ID and Name.

I see that Che has answered while I was working up this demo, but what the heck:

I’m simply using the index of the for: loop as the ID of the button, and the str() of that index as the Name, Label, and Tooltip of the button, but you can obviously set those to whatever you want - in practice, I usually create a list of dictionaries containing the properties for my controls, and then loop through that.

Notice that (in your OnClick events) it’s easier to retrieve the ID than the Name.

import wx, sys
try:
import wx.lib.inspection
except ImportError:
pass

class MyFrame(wx.Frame):

ID_LOAD = wx.NewId()

def __init__(self, parent, id, title, size, style = wx.DEFAULT_FRAME_STYLE ):
    wx.Frame.__init__(self, parent, id, title, size=size, style=style)
    self.CreateStatusBar()

    pnl = wx.Panel(self)
   
    gsLeft = wx.GridSizer(4, 2, 2, 2)  # rows, cols, vgap, hgap
    middleBox = wx.BoxSizer(wx.HORIZONTAL)
    gsRight = wx.GridSizer(4, 4, 2, 2)  # rows, cols, vgap, hgap

    for btn in xrange(24):
        b = wx.Button(pnl, btn, label=str(btn), name=str(btn))
        b.SetToolTip(wx.ToolTip(str(btn)))
        if btn > 7:
            gsRight.Add(b)

            self.Bind(wx.EVT_BUTTON, self.OnClickRight, b)
        else:
            gsLeft.Add(b)
            self.Bind(wx.EVT_BUTTON, self.OnClickLeft, b)

    outerSizer = wx.BoxSizer(wx.HORIZONTAL)

    outerSizer.Add(gsLeft)
    outerSizer.Add(middleBox, 1, wx.EXPAND)
    outerSizer.Add(gsRight)
    pnl.SetSizer(outerSizer)
       
       
def OnClickLeft(self, event):

    self.SetStatusText("Left - " + str(event.GetId()) + "  Name - " + event.GetEventObject().Name)

def OnClickRight(self, event):
    self.SetStatusText("Right - " + str(event.GetId()) + "  Name - " + event.GetEventObject().Name)

class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, “Testing a grid of buttons”,wx.Size(600,200))
frame.Show()
return True

def main(argv=None):
if argv is None:
argv = sys.argv
app = MyApp(0)
#wx.lib.inspection.InspectionTool().Show()
app.MainLoop()

if name == ‘main’:
main()

···

On Wed, Sep 7, 2011 at 8:07 AM, SpiritualMadMan madrucke@yahoo.com wrote:

Basically what I want is 2 x 16 Grid of buttons that I can use a

single EVT_ and an index to decide which of the buttons was Clicked

on.

Even better would be an EVT_ for the right side of 16 buttons and an

EVT_ for left side of 8 buttons…

Is this possible in wxPython?

Thanks to both of you for your help!

I will be working this at a later date, unfortunately.

But, the good news is, is that I got my other menu system working!

And, it will allow the project to go forward. Yeah! :slight_smile:

smm

or use the nifty "lambda trick" (or functools):

http://wiki.wxpython.org/Passing%20Arguments%20to%20Callbacks

-Chris

···

On 9/7/11 9:30 AM, C M wrote:

On Wed, Sep 7, 2011 at 11:07 AM, SpiritualMadMan<madrucke@yahoo.com> wrote:

Basically what I want is 2 x 16 Grid of buttons that I can use a
single EVT_ and an index to decide which of the buttons was Clicked
on.

3) In the event handler you can get which button the event came from.

def OnButtonPressed(self,event):
      button_pressed = event.GetEventObject()

At that point you might have some kind of dictionary or something that
tells you what to do based on which button was pressed. You could use
the label as the key, and you'd get the label by continuing in (3)....

     label = button_pressed.GetLabel()

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Thanks All,

I modified what Marc Tompkins shared and have a working Button Menu
Class
[code]
# Base Class for Button Version of Main Menu
class Menu_Btn(wx.Dialog):
    def __init__(self, *args, **kwds):
        # begin wxGlade: Menu_2.__init__
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
        wx.Dialog.__init__(self, *args, **kwds)
        self.label_1 = wx.StaticText(self, -1, " Main Menu For ")
        self.UUT_Name = wx.StaticText(self, -1, "Name for UUT")
        self.label_2 = wx.StaticText(self, -1, "")
        self.button_1 = wx.Button(self, -1, "")
        self.command_1 = wx.Button(self, -1, "Rerun Last Module")
        self.button_2 = wx.Button(self, -1, "")
        self.Alpha_1 = wx.StaticText(self, -1, "")
        self.button_3 = wx.Button(self, -1, "")
        self.command_2 = wx.Button(self, -1, "Print Ticket")
        self.button_4 = wx.Button(self, -1, "")
        self.Alpha_2 = wx.StaticText(self, -1, "")
        self.button_5 = wx.Button(self, -1, "")
        self.command_3 = wx.Button(self, -1, "Next UUT (Same Type)")
        self.button_6 = wx.Button(self, -1, "")
        self.Alpha_3 = wx.StaticText(self, -1, "")
        self.button_7 = wx.Button(self, -1, "")
        self.command_4 = wx.Button(self, -1, "Run All Modules End To
End")
        self.button_8 = wx.Button(self, -1, "")
        self.Alpha_4 = wx.StaticText(self, -1, "")
        self.button_9 = wx.Button(self, -1, "")
        self.command_5 = wx.Button(self, -1, "View Instrument Set-Up
Instructions")
        self.button_10 = wx.Button(self, -1, "")
        self.Alpha_5 = wx.StaticText(self, -1, "")
        self.button_11 = wx.Button(self, -1, "")
        self.command_6 = wx.Button(self, -1, "Access IETM")
        self.button_12 = wx.Button(self, -1, "")
        self.Alpha_6 = wx.StaticText(self, -1, "")
        self.button_13 = wx.Button(self, -1, "")
        self.command_7 = wx.Button(self, -1, "EXIT")
        self.button_14 = wx.Button(self, -1, "")
        self.Alpha_7 = wx.StaticText(self, -1, "")
        self.button_15 = wx.Button(self, -1, "")
        self.command_8 = wx.Button(self, -1, "Next Menu")
        self.button_16 = wx.Button(self, -1, "")
        self.Alpha_8 = wx.StaticText(self, -1, "")
        self.label_55 = wx.StaticText(self, -1, " Color Code: ")
        self.NotRun = wx.StaticText(self, -1, " Not Run ")
        self.Passed = wx.StaticText(self, -1, " Passed ")
        self.Failed = wx.StaticText(self, -1, " Failed ")
        self.NotImp = wx.StaticText(self, -1, " Not Implemented ")

        for i in range(16):
            self.Bind(wx.EVT_BUTTON, self.OnSelectionClick,
getattr(self, "button_%d" %(i+1)))

        for j in range(8):
            self.Bind(wx.EVT_BUTTON, self.OnCommandClick,
getattr(self, "command_%d" %(j+1)))

        self.__set_properties()
        self.__do_layout()
        self.UpDateMenu()
        # end wxGlade

    def __set_properties(self):
        # begin wxGlade: Menu_2.__set_properties
        self.SetTitle("Main Menu")
        self.SetSize((640, 700))
        self.SetBackgroundColour(wx.Colour(200, 200, 200))
        self.label_1.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.UUT_Name.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_1.SetMinSize((311, 34))
        self.button_1.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.command_1.SetBackgroundColour(wx.Colour(104, 100, 255))
        self.command_1.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_2.SetMinSize((101, 29))
        self.button_2.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Alpha_1.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.button_3.SetMinSize((101, 29))
        self.button_3.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.command_2.SetBackgroundColour(wx.Colour(104, 100, 255))
        self.command_2.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_4.SetMinSize((101, 29))
        self.button_4.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Alpha_2.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.button_5.SetMinSize((101, 29))
        self.button_5.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.command_3.SetBackgroundColour(wx.Colour(104, 100, 255))
        self.command_3.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_6.SetMinSize((101, 29))
        self.button_6.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Alpha_3.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.button_7.SetMinSize((101, 29))
        self.button_7.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.command_4.SetBackgroundColour(wx.Colour(104, 100, 255))
        self.command_4.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_8.SetMinSize((101, 29))
        self.button_8.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Alpha_4.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.button_9.SetMinSize((101, 29))
        self.button_9.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.command_5.SetBackgroundColour(wx.Colour(104, 100, 255))
        self.command_5.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_10.SetMinSize((101, 29))
        self.button_10.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Alpha_5.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.button_11.SetMinSize((101, 29))
        self.button_11.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.command_6.SetBackgroundColour(wx.Colour(104, 100, 255))
        self.command_6.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_12.SetMinSize((101, 29))
        self.button_12.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Alpha_6.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.button_13.SetMinSize((101, 29))
        self.button_13.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.command_7.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_14.SetMinSize((101, 29))
        self.button_14.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Alpha_7.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.button_15.SetMinSize((101, 29))
        self.button_15.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.command_8.SetBackgroundColour(wx.Colour(104, 100, 255))
        self.command_8.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.button_16.SetMinSize((101, 29))
        self.button_16.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Alpha_8.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
        self.label_55.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.NotRun.SetBackgroundColour(wx.Colour(250, 255, 15))
        self.NotRun.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Passed.SetBackgroundColour(wx.Colour(35, 255, 0))
        self.Passed.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.Failed.SetBackgroundColour(wx.Colour(255, 30, 0))
        self.Failed.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        self.NotImp.SetBackgroundColour(wx.Colour(104, 100, 255))
        self.NotImp.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: Menu_2.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
        grid_sizer_1 = wx.GridSizer(16, 2, 0, 0)
        sizer_1.Add(self.label_1, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
        sizer_1.Add(self.UUT_Name, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
        sizer_1.Add(self.label_2, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_1, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.command_1, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_2, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.Alpha_1, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_3, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.command_2, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_4, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.Alpha_2, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_5, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.command_3, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_6, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.Alpha_3, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_7, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.command_4, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_8, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.Alpha_4, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_9, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.command_5, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_10, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.Alpha_5, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_11, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.command_6, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_12, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.Alpha_6, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_13, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.command_7, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_14, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.Alpha_7, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_15, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.command_8, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.button_16, 0, wx.EXPAND, 0)
        grid_sizer_1.Add(self.Alpha_8, 0, wx.EXPAND, 0)
        sizer_4.Add(grid_sizer_1, 1, wx.EXPAND, 0)
        sizer_3.Add(sizer_4, 1, wx.EXPAND, 0)
        sizer_1.Add(sizer_3, 1, wx.EXPAND, 0)
        sizer_5.Add(self.label_55, 0, wx.ALIGN_BOTTOM, 0)
        sizer_5.Add(self.NotRun, 0, wx.ALIGN_BOTTOM, 0)
        sizer_5.Add(self.Passed, 0, 0, 0)
        sizer_5.Add(self.Failed, 0, wx.ALIGN_BOTTOM, 0)
        sizer_5.Add(self.NotImp, 0, wx.ALIGN_RIGHT, 0)
        sizer_1.Add(sizer_5, 0, 0, 0)
        self.SetSizer(sizer_1)
        self.Layout()
        self.Centre()

    def OnSelectionClick(self,event):
        # print "On Selection Click: " + str(event.GetId())
        MenuSelection = (abs(event.GetId()) - 247)/2
        print "On Selection Click: " + str(MenuSelection)
        if MenuSelection <= int(TC_Config.Test_Modules):
            TC_Config.TPS_Status = "Running"
            TC_Config.Error_Message = "No Error"
            TC_Config.CurrentModule = MenuSelection
            self.Hide()

        event.Skip()

    def OnCommandClick(self, event):
        print "On Command Click: " + str(event.GetId())
        if event.GetId()==-275:
            TC_Config.TPS_Status = "Exit"
            self.Destroy()

    # Uses the Variables set in TC_Config to setup or refresh the Main
Menu
    def UpDateMenu(self):
        self.Selection=[]
        for i in range(16):
            self.Selection.append(getattr(self, "button_%d" %(i+1)) )
            self.Selection[i].SetLabel(TC_Config.ModuleName[i])
            print TC_Config.ModuleName[i] + " Status: " +
TC_Config.ModuleStatus[i]
            if TC_Config.ModuleName[i] != "":
                # Set "Yellow" Highlight if "Not Run"
                if TC_Config.ModuleStatus[i] == "Not Run":

self.Selection[i].SetBackgroundColour(wx.Colour(255, 255, 0))
                # Set "Green" highlight if "Passed"
                elif TC_Config.ModuleStatus[i] == "Passed":
                    self.Selection[i].SetBackgroundColour(wx.Colour(0,
255, 0))
                # Set "Red" highlight if "Falied"
                elif TC_Config.ModuleStatus[i] == "Failed":

self.Selection[i].SetBackgroundColour(wx.Colour(255, 0, 0))

# end of class Menu_Btn
[/code]
NOTE: The Button Event ID has to be tailored once the Class is in its
correct place in the Application. It was a bit of a shock to see my
Class stop working went I moved it from the text bed into my App. :slight_smile:

I am sure that wxGlade adds some stuff that doesn;t need to be there.

And, I am pretty sure most of you guys that have been programming
longer than my four weeks can come up with all sorts of improvements.

Have at :slight_smile:

Of course I probably wouldn't understand any of them...

The above code is instantiated by the following code:
[code]
# This is the Master Control Function
def Test_Control(ptf):
    # Initialize the UUT and Menu Information
    ptf.get("UUT_Info")()
    ptf.get("Menu_Info")()

    # The False prevents print statements from opening a command
window
    app = wx.App(False)
    wx.InitAllImageHandlers()
    # Create the Logging Screen
    LogScrn = Lines_24(None, -1, "")
    LogScrn.AddLine("This is the Initial Log Screen Entry: ")
    LogScrn.Show()

    # Create the initial tcDict Entry
    tcDict = {"LogScrn":LogScrn}

    # Create the UUT Information Display
    # LogScrn.AddLine("Creating UUT Information Display")
    UUTInfo = DiaInfoUUT(None, -1, "")
    UUTInfo.Man_Name.SetLabel(" " + TC_Config.Man_Name)
    UUTInfo.ModNumber.SetLabel(" " + TC_Config.ModNumber)
    UUTInfo.MilDesig.SetLabel(" " + TC_Config.MilDesig)
    UUTInfo.Nomen.SetLabel(" " + TC_Config.Nomen)
    UUTInfo.PartNo.SetLabel(" " + TC_Config.PartNo)
    UUTInfo.SerNo.SetLabel(" " + TC_Config.SerNo)
    UUTInfo.Revision.SetLabel(" " + TC_Config.Rev)
    UUTInfo.ShowModal()

    # Create the Main Menu
    # Main_Menu = Menu_2(None, -1, "")
    Main_Menu = Menu_Btn(None, -1, "")
    # Enter the Main Menu Loop
    while TC_Config.TPS_Status != "Exit":
        LogScrn.AddLine("Creating the Main Menu")
        Main_Menu.ShowModal()
        if TC_Config.TPS_Status == "Exit":
            # Don't leave the Logging Display Orphaned on the Screen
            # If exiting from UUT Info
            LogScrn.Destroy()
        else:
            # Always test that it is Safe to turn on before continuing
            if TC_Config.STTO == False:
                # False try running Safe To Turn On
                TC_Config.STTO = ptf.get("SafeToTurnOn")(tcDict)

            # Not! elseif because we need to have a separate test
            # after we have (re) attempted to run Safe To Turn On
            if TC_Config.STTO == True:
                LogScrn.AddLine("UUT Passed Safe To Turn On")
                ptf.get("Module_Launcher")(tcDict)
                Main_Menu.UpDateMenu()
    # Don't leave the Logging Display Orphaned on the Screen when menu
Exits
    LogScrn.Destroy()

    app.MainLoop()
[/code]

I would separate all of those properties from the code - it makes things a lot easier to read and to maintain/extend. So I’d set up a list of dictionaries (or a dictionary of dictionaries if you prefer; lists are easy to step through with an index, and they’re always in the same order, while dictionaries can use “meaningful” key names but don’t have a predictable order) to hold your names/fonts/colors/sizes/etc., and then step through that list or dictionary to create and place the controls.

I also don’t like to use generic control names: e.g. button_12. Either you actually need to refer to the control by name - in which case the name ought to be meaningful, like button_Start - or you don’t… in which case it’s a lot more efficient to put the control in a dictionary and never refer to it by name at all, e.g. btn[12].

Taking a closer look at your code, I realize that wxGlade is driving a lot of those choices. Speaking as a former VB6 guy myself - hated the language, loved the layout tools - my advice is to get out of the Glade habit as early as possible. It’s not really all that good at automatic layout, and the code it generates is hard to read and impossible to maintain. wxPython’s sizers take a little getting used to, but once you do get used to them it’s not so hard to do a layout on the back of an envelope and write good, readable code in a hurry. If Glade were as clean and easy to use as VB, I might forgive the crap code it generates; if it produced clean code, I could forgive its clumsiness; as it is, I recommend that you KIWF.

···

On Thu, Sep 8, 2011 at 1:38 PM, SpiritualMadMan madrucke@yahoo.com wrote:

Thanks All,

I modified what Marc Tompkins shared and have a working Button Menu

Class

And, I am pretty sure most of you guys that have been programming

longer than my four weeks can come up with all sorts of improvements.

First:

It is much better tp post a complete working (but small) example, so we can easily test and suggest changes to your code:

http://wiki.wxpython.org/MakingSampleApps

Second:

When you post code, post it as at attachment, rather than inline in the email -- email clients wreak havoc on whitespace.

Third:

I second antoher poster's thoughts about wxGlade -- in fact, virtually any GUI-Builder -- this is crying out for a more code-generated layout -- that's an enourmous amount of repeated code.

See the enclosed example for a start.

Note that the buttons are numbered 0-n, so you could have a list of button attributes, event handlers, whatever, that you could easily call to do more stuff.

-Chris

ButtonArray.py (1.22 KB)

···

On 9/8/11 1:38 PM, SpiritualMadMan wrote:

# Base Class for Button Version of Main Menu
class Menu_Btn(wx.Dialog):
     def __init__(self, *args, **kwds):
         # begin wxGlade: Menu_2.__init__
         kwds["style"] = wx.DEFAULT_DIALOG_STYLE
         wx.Dialog.__init__(self, *args, **kwds)
         self.label_1 = wx.StaticText(self, -1, " Main Menu For ")
         self.UUT_Name = wx.StaticText(self, -1, "Name for UUT")
         self.label_2 = wx.StaticText(self, -1, "")
         self.button_1 = wx.Button(self, -1, "")
         self.command_1 = wx.Button(self, -1, "Rerun Last Module")
         self.button_2 = wx.Button(self, -1, "")
         self.Alpha_1 = wx.StaticText(self, -1, "")
         self.button_3 = wx.Button(self, -1, "")
         self.command_2 = wx.Button(self, -1, "Print Ticket")
         self.button_4 = wx.Button(self, -1, "")
         self.Alpha_2 = wx.StaticText(self, -1, "")
         self.button_5 = wx.Button(self, -1, "")
         self.command_3 = wx.Button(self, -1, "Next UUT (Same Type)")
         self.button_6 = wx.Button(self, -1, "")
         self.Alpha_3 = wx.StaticText(self, -1, "")
         self.button_7 = wx.Button(self, -1, "")
         self.command_4 = wx.Button(self, -1, "Run All Modules End To
End")
         self.button_8 = wx.Button(self, -1, "")
         self.Alpha_4 = wx.StaticText(self, -1, "")
         self.button_9 = wx.Button(self, -1, "")
         self.command_5 = wx.Button(self, -1, "View Instrument Set-Up
Instructions")
         self.button_10 = wx.Button(self, -1, "")
         self.Alpha_5 = wx.StaticText(self, -1, "")
         self.button_11 = wx.Button(self, -1, "")
         self.command_6 = wx.Button(self, -1, "Access IETM")
         self.button_12 = wx.Button(self, -1, "")
         self.Alpha_6 = wx.StaticText(self, -1, "")
         self.button_13 = wx.Button(self, -1, "")
         self.command_7 = wx.Button(self, -1, "EXIT")
         self.button_14 = wx.Button(self, -1, "")
         self.Alpha_7 = wx.StaticText(self, -1, "")
         self.button_15 = wx.Button(self, -1, "")
         self.command_8 = wx.Button(self, -1, "Next Menu")
         self.button_16 = wx.Button(self, -1, "")
         self.Alpha_8 = wx.StaticText(self, -1, "")
         self.label_55 = wx.StaticText(self, -1, " Color Code: ")
         self.NotRun = wx.StaticText(self, -1, " Not Run ")
         self.Passed = wx.StaticText(self, -1, " Passed ")
         self.Failed = wx.StaticText(self, -1, " Failed ")
         self.NotImp = wx.StaticText(self, -1, " Not Implemented ")

         for i in range(16):
             self.Bind(wx.EVT_BUTTON, self.OnSelectionClick,
getattr(self, "button_%d" %(i+1)))

         for j in range(8):
             self.Bind(wx.EVT_BUTTON, self.OnCommandClick,
getattr(self, "command_%d" %(j+1)))

         self.__set_properties()
         self.__do_layout()
         self.UpDateMenu()
         # end wxGlade

     def __set_properties(self):
         # begin wxGlade: Menu_2.__set_properties
         self.SetTitle("Main Menu")
         self.SetSize((640, 700))
         self.SetBackgroundColour(wx.Colour(200, 200, 200))
         self.label_1.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.UUT_Name.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_1.SetMinSize((311, 34))
         self.button_1.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.command_1.SetBackgroundColour(wx.Colour(104, 100, 255))
         self.command_1.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_2.SetMinSize((101, 29))
         self.button_2.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Alpha_1.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.button_3.SetMinSize((101, 29))
         self.button_3.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.command_2.SetBackgroundColour(wx.Colour(104, 100, 255))
         self.command_2.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_4.SetMinSize((101, 29))
         self.button_4.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Alpha_2.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.button_5.SetMinSize((101, 29))
         self.button_5.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.command_3.SetBackgroundColour(wx.Colour(104, 100, 255))
         self.command_3.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_6.SetMinSize((101, 29))
         self.button_6.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Alpha_3.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.button_7.SetMinSize((101, 29))
         self.button_7.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.command_4.SetBackgroundColour(wx.Colour(104, 100, 255))
         self.command_4.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_8.SetMinSize((101, 29))
         self.button_8.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Alpha_4.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.button_9.SetMinSize((101, 29))
         self.button_9.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.command_5.SetBackgroundColour(wx.Colour(104, 100, 255))
         self.command_5.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_10.SetMinSize((101, 29))
         self.button_10.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Alpha_5.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.button_11.SetMinSize((101, 29))
         self.button_11.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.command_6.SetBackgroundColour(wx.Colour(104, 100, 255))
         self.command_6.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_12.SetMinSize((101, 29))
         self.button_12.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Alpha_6.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.button_13.SetMinSize((101, 29))
         self.button_13.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.command_7.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_14.SetMinSize((101, 29))
         self.button_14.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Alpha_7.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.button_15.SetMinSize((101, 29))
         self.button_15.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.command_8.SetBackgroundColour(wx.Colour(104, 100, 255))
         self.command_8.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.button_16.SetMinSize((101, 29))
         self.button_16.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Alpha_8.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.NORMAL, 0, ""))
         self.label_55.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.NotRun.SetBackgroundColour(wx.Colour(250, 255, 15))
         self.NotRun.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Passed.SetBackgroundColour(wx.Colour(35, 255, 0))
         self.Passed.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.Failed.SetBackgroundColour(wx.Colour(255, 30, 0))
         self.Failed.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         self.NotImp.SetBackgroundColour(wx.Colour(104, 100, 255))
         self.NotImp.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL,
wx.BOLD, 0, ""))
         # end wxGlade

     def __do_layout(self):
         # begin wxGlade: Menu_2.__do_layout
         sizer_1 = wx.BoxSizer(wx.VERTICAL)
         sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
         sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
         sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
         grid_sizer_1 = wx.GridSizer(16, 2, 0, 0)
         sizer_1.Add(self.label_1, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
         sizer_1.Add(self.UUT_Name, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
         sizer_1.Add(self.label_2, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_1, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.command_1, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_2, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.Alpha_1, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_3, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.command_2, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_4, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.Alpha_2, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_5, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.command_3, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_6, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.Alpha_3, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_7, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.command_4, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_8, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.Alpha_4, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_9, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.command_5, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_10, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.Alpha_5, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_11, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.command_6, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_12, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.Alpha_6, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_13, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.command_7, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_14, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.Alpha_7, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_15, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.command_8, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.button_16, 0, wx.EXPAND, 0)
         grid_sizer_1.Add(self.Alpha_8, 0, wx.EXPAND, 0)
         sizer_4.Add(grid_sizer_1, 1, wx.EXPAND, 0)
         sizer_3.Add(sizer_4, 1, wx.EXPAND, 0)
         sizer_1.Add(sizer_3, 1, wx.EXPAND, 0)
         sizer_5.Add(self.label_55, 0, wx.ALIGN_BOTTOM, 0)
         sizer_5.Add(self.NotRun, 0, wx.ALIGN_BOTTOM, 0)
         sizer_5.Add(self.Passed, 0, 0, 0)
         sizer_5.Add(self.Failed, 0, wx.ALIGN_BOTTOM, 0)
         sizer_5.Add(self.NotImp, 0, wx.ALIGN_RIGHT, 0)
         sizer_1.Add(sizer_5, 0, 0, 0)
         self.SetSizer(sizer_1)
         self.Layout()
         self.Centre()

     def OnSelectionClick(self,event):
         # print "On Selection Click: " + str(event.GetId())
         MenuSelection = (abs(event.GetId()) - 247)/2
         print "On Selection Click: " + str(MenuSelection)
         if MenuSelection<= int(TC_Config.Test_Modules):
             TC_Config.TPS_Status = "Running"
             TC_Config.Error_Message = "No Error"
             TC_Config.CurrentModule = MenuSelection
             self.Hide()

         event.Skip()

     def OnCommandClick(self, event):
         print "On Command Click: " + str(event.GetId())
         if event.GetId()==-275:
             TC_Config.TPS_Status = "Exit"
             self.Destroy()

     # Uses the Variables set in TC_Config to setup or refresh the Main
Menu
     def UpDateMenu(self):
         self.Selection=
         for i in range(16):
             self.Selection.append(getattr(self, "button_%d" %(i+1)) )
             self.Selection[i].SetLabel(TC_Config.ModuleName[i])
             print TC_Config.ModuleName[i] + " Status: " +
TC_Config.ModuleStatus[i]
             if TC_Config.ModuleName[i] != "":
                 # Set "Yellow" Highlight if "Not Run"
                 if TC_Config.ModuleStatus[i] == "Not Run":

self.Selection[i].SetBackgroundColour(wx.Colour(255, 255, 0))
                 # Set "Green" highlight if "Passed"
                 elif TC_Config.ModuleStatus[i] == "Passed":
                     self.Selection[i].SetBackgroundColour(wx.Colour(0,
255, 0))
                 # Set "Red" highlight if "Falied"
                 elif TC_Config.ModuleStatus[i] == "Failed":

self.Selection[i].SetBackgroundColour(wx.Colour(255, 0, 0))

# end of class Menu_Btn
[/code]
NOTE: The Button Event ID has to be tailored once the Class is in its
correct place in the Application. It was a bit of a shock to see my
Class stop working went I moved it from the text bed into my App.:slight_smile:

I am sure that wxGlade adds some stuff that doesn;t need to be there.

And, I am pretty sure most of you guys that have been programming
longer than my four weeks can come up with all sorts of improvements.

Have at:)

Of course I probably wouldn't understand any of them...

The above code is instantiated by the following code:
[code]
# This is the Master Control Function
def Test_Control(ptf):
     # Initialize the UUT and Menu Information
     ptf.get("UUT_Info")()
     ptf.get("Menu_Info")()

     # The False prevents print statements from opening a command
window
     app = wx.App(False)
     wx.InitAllImageHandlers()
     # Create the Logging Screen
     LogScrn = Lines_24(None, -1, "")
     LogScrn.AddLine("This is the Initial Log Screen Entry: ")
     LogScrn.Show()

     # Create the initial tcDict Entry
     tcDict = {"LogScrn":LogScrn}

     # Create the UUT Information Display
     # LogScrn.AddLine("Creating UUT Information Display")
     UUTInfo = DiaInfoUUT(None, -1, "")
     UUTInfo.Man_Name.SetLabel(" " + TC_Config.Man_Name)
     UUTInfo.ModNumber.SetLabel(" " + TC_Config.ModNumber)
     UUTInfo.MilDesig.SetLabel(" " + TC_Config.MilDesig)
     UUTInfo.Nomen.SetLabel(" " + TC_Config.Nomen)
     UUTInfo.PartNo.SetLabel(" " + TC_Config.PartNo)
     UUTInfo.SerNo.SetLabel(" " + TC_Config.SerNo)
     UUTInfo.Revision.SetLabel(" " + TC_Config.Rev)
     UUTInfo.ShowModal()

     # Create the Main Menu
     # Main_Menu = Menu_2(None, -1, "")
     Main_Menu = Menu_Btn(None, -1, "")
     # Enter the Main Menu Loop
     while TC_Config.TPS_Status != "Exit":
         LogScrn.AddLine("Creating the Main Menu")
         Main_Menu.ShowModal()
         if TC_Config.TPS_Status == "Exit":
             # Don't leave the Logging Display Orphaned on the Screen
             # If exiting from UUT Info
             LogScrn.Destroy()
         else:
             # Always test that it is Safe to turn on before continuing
             if TC_Config.STTO == False:
                 # False try running Safe To Turn On
                 TC_Config.STTO = ptf.get("SafeToTurnOn")(tcDict)

             # Not! elseif because we need to have a separate test
             # after we have (re) attempted to run Safe To Turn On
             if TC_Config.STTO == True:
                 LogScrn.AddLine("UUT Passed Safe To Turn On")
                 ptf.get("Module_Launcher")(tcDict)
                 Main_Menu.UpDateMenu()
     # Don't leave the Logging Display Orphaned on the Screen when menu
Exits
     LogScrn.Destroy()

     app.MainLoop()

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Chris,

The only two places I have access to from my IT Paranoiac Locked Down
Computer at Work is here, on Google, and DaniWeb.

I hesitated posting such a long post here because it didn't look like
there was a lot of code posting. And, I didn't see a way to attach the
code here.

I do have one ?former? poster's e-mail who has been working with me
and I sent a copy of the app to him, not so much for help, but so that
he could see some of the fruits of his efforts to help me.

I thought that only fair.

I also have Robin's e-mail. But, I would not want to clutter his in
box or make him feel obligated by sending it to his in-box.

After all he probably has literally thousands of requests a day
already.

If the Google Groups can accept attachments it is non-obvious to this
stressed out programmer. :slight_smile: [ppointers gladly accepted]

AS for posting once I get home...

By the time I get home I am so exhausted from work related stress all
I want to do is watch Star Trek Voyager on NetFlix and go to bed. Only
watched one episode last night.

Honestly, being forced to go from what I know fairly well, VB6, to
Python w/GUI in a matter of weeks has been incredibly stressful for a
(now) slow learning 59 year old brain.

The HELP I have recieved here has been (possibly literally) a
lifesaver.

I can not thank you folks enough.

And, I will give attribution in any formal documentation once my
project is accepted by my peers.

Again, thanks, and, I am sure you'll get a chuckle now and then from
the gaps in my understanding of things oh so obvious to you folks...

:slight_smile:
smm

Hi,

...

If the Google Groups can accept attachments it is non-obvious to this
stressed out programmer. :slight_smile: [ppointers gladly accepted]

Yes, but:)

You can't do it using google groups web client but you can if you are replying from e.g. Thunderbird.

What I do as I like to have a local archive anyhow is:

- I sign up to google groups with a non google email (as otherwise I don't see my posts)
- setup e.g. thunderbird to read that "non google email id" and then post/reply from within Thunderbird

Werner

···

On 09/09/2011 11:05 AM, SpiritualMadMan wrote:

If the Google Groups can accept attachments it is non-obvious to this
stressed out programmer. :slight_smile: [ppointers gladly accepted]

Yes, but:)

You can't do it using google groups web client

This is a major limitation -- I sure wish Google would address it!

but you can if you are
replying from e.g. Thunderbird.

I don't see why a gmail reply wouldn't work also -- but as it happens. I use thunderbird, too.

The only two places I have access to from my IT Paranoiac Locked Down
Computer at Work is here, on Google, and DaniWeb.

got to love those IT Paranoiacs!

I hesitated posting such a long post here because it didn't look like
there was a lot of code posting.

code is posted frequently here, but you are right, we don't encourage long codes -- I suppose there are bandwidth issues, but mostly, it's not that useful, who of us has time to look through someone else's long pile of code?

So the goal is to post as small a sample as possible that demonstrates the issue, but is also fully stand-alone runnable. As a bonus, you'll find that writing such a sample often teaches you a lot.

In your case -- you weren't really asking a question anymore -- you had it working, but I assume you did want feedback, so the same suggestions apply.

Anyway, it's not about breaking or not breaking "rules", it's about what you can do to make it as easy as possible for folks to help you.

Honestly, being forced to go from what I know fairly well, VB6, to
Python w/GUI in a matter of weeks has been incredibly stressful for a
(now) slow learning 59 year old brain.

you seem to be doing well with it though -- I hope once you get over the hump, it will feel more fun than stressful.

I can not thank you folks enough.

A good group, this.

Good luck,

--Chris

···

On 9/9/11 3:57 AM, werner wrote:
On 9/9/11 2:05 AM, SpiritualMadMan wrote:

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

They have addressed it. There is a new browser UI for Groups that does allow you to add attachments to messages created in the browser UI. It looks like you may still need to opt-in to use the new UI however, look for a "Preview the new Google Groups" link. Unfortunately they changed the LnF of the browser UI sometime in the last couple days in what I feel was a step backwards!

···

On 9/9/11 8:44 AM, Chris.Barker wrote:

On 9/9/11 3:57 AM, werner wrote:

If the Google Groups can accept attachments it is non-obvious to this
stressed out programmer. :slight_smile: [ppointers gladly accepted]

Yes, but:)

You can't do it using google groups web client

This is a major limitation -- I sure wish Google would address it!

--
Robin Dunn
Software Craftsman

Chris,

The only two places I have access to from my IT Paranoiac Locked Down
Computer at Work is here, on Google, and DaniWeb.

I hesitated posting such a long post here because it didn't look like
there was a lot of code posting. And, I didn't see a way to attach the
code here.

I do have one ?former? poster's e-mail who has been working with me
and I sent a copy of the app to him,

Since you seem to be saying you sent wxPython code via an email to
someone (from work?) am I right in saying you can subscribe your
email, readable at work, to the listserver? IMO, that is the best way
to read this group. I have this separate email account just for this
group, using Gmail. I can easily attach .py files or image files, I
can search the huge trove of emails, star particularly helpful ones,
etc. I couldn't work on wxPython projects without all this at this
point. But whether it's Gmail or some other mail program shouldn't
matter much (I just like Gmail).

I read the Python language group (comp.language.python) via Google
Groups, because it's less important to me and I'd rather not receive
all those (mostly irrelevant) emails and I essentially never have to
attach things there.

I also have Robin's e-mail. But, I would not want to clutter his in
box or make him feel obligated by sending it to his in-box.

It's all about emailing this group, really--not individuals, for the
most part. (Although an occasional email about a project, like to
Andrea regarding a follow-up question on an AGW widget, might be
warranted, although even then it is best to do it "out in the air").

After all he probably has literally thousands of requests a day
already.

Many of which are from Hollywood regarding the upcoming "The Robin
Dunn Story". :smiley:

Again, thanks, and, I am sure you'll get a chuckle now and then from
the gaps in my understanding of things oh so obvious to you folks...

If so, it's only a chuckle of commiseration or remembrance where we
recently were. It's not a snarky group at all.

Chris Barker said:

I second another poster's thoughts about wxGlade -- in fact, virtually any GUI-Builder --
this is crying out for a more code-generated layout -- that's an enourmous amount of
repeated code.

I third that (with one reservation). You absolutely do not want to
have all those essentially identical lines, it makes it a nightmare to
maintain and just makes managing the code 20x worse.

That said, I have used Boa Constructor and for the most part can live
with the way it generates the GUI part of the code. It's a
compromise, in the following way: if I am just doing a small and
somewhat varied GUI, I'll probably lay it out with Boa and let Boa
generate the code. But if I'm doing a large array of nearly identical
items like your button array, I would simply put *that part* in a loop
(as I mentioned above), not worry about attaching a variable name to
each button, and reduce the code complexity greatly. I haven't looked
at Chris's code yet but I'm sure that's just what he did.

Che

···

On Fri, Sep 9, 2011 at 5:05 AM, SpiritualMadMan <madrucke@yahoo.com> wrote:

hmmm -- it seem Guido is letting others at Google use his Time Machine -- this could be dangerous!

Thanks for the pointer -- that is a nice improvement.

-Chris

···

On 9/9/11 9:51 AM, Robin Dunn wrote:

This is a major limitation -- I sure wish Google would address it!

They have addressed it.

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Ouch!

Persons in the USMC NMCI system are *STILL* using IE7

Do not know if the Navy side has IE8 yet or not...

So, the new Interface is not available to us at work...

Mike Sr.

Is there a way to successfully open an HTML file in a wxpython window where
javascript will execute? Particularly I'd like to open the CKEditor sample
called fullpage.html.

Thanks,

Gary

Currently it depends on your target platform. On Windows you can embed the IE ActiveX control with wx.lib.iewin. On OSX you can use wx.webkit to embed the Safari control. On wxGTk you can try something like this if you have a new enough GTK and have the right packages installed: wxGTKWebKit - wxPyWiki

Soon we'll have 2 better options available. There was a GSoC project this year to add classes to wx that put a single consistent API on top of using the various native platform browser controls mentioned above. There are still some issues being ironed out, but it sounds like most people are happy with it so far.

Also the wxWebKit project is now in a useable state. It uses wx to implement the drawing layer for the webkit library, and provides a wx API on top. (This is similar to how the StyleTextCtrl is wx on the bottom, Scintilla in the middle, and wx on top.) The benefit is that it is using the same code on all platforms, and is able to expose more functionality without needing to worry about things that may or may not be doable with the native component on other platforms or alternate backends. I expect to see some official releases in the not too distant future.

Here's a quick story to illustrate the wxWebKit rendering quality: I've recently been involved with a project that is using wxWebKit, and I had some code in place that would fall back to wx.lib.iewin if it was unable to load wxWebKit for some reason. While chasing down a bug I noticed that in one corner case the fallback was happening and in other cases the wxWebKit components were being used. The only way I could tell the difference between the two was that one of the Javascript snippets loaded by the page was misbehaving on the IE component so a status message wasn't being displayed correctly. Otherwise the two cases looked essentially the same visually.

···

On 9/19/11 10:17 AM, Gary Hawkins wrote:

Is there a way to successfully open an HTML file in a wxpython window where
javascript will execute? Particularly I'd like to open the CKEditor sample
called fullpage.html.

--
Robin Dunn
Software Craftsman

You can see this example that uses IE (Activex) on windows and webkit on gtk:

http://code.google.com/p/rad2py/source/browse/ide2py/browser.py

You need install standard packages:

on windows, pywin32 (pywintypes)
on linux (and mac?), python-webkit (gtk)

Regards

Mariano Reingart
http://www.sistemasagiles.com.ar

···

On Mon, Sep 19, 2011 at 2:51 PM, Robin Dunn <robin@alldunn.com> wrote:

On 9/19/11 10:17 AM, Gary Hawkins wrote:

Is there a way to successfully open an HTML file in a wxpython window
where
javascript will execute? Particularly I'd like to open the CKEditor
sample
called fullpage.html.

Currently it depends on your target platform. On Windows you can embed the
IE ActiveX control with wx.lib.iewin. On OSX you can use wx.webkit to embed
the Safari control. On wxGTk you can try something like this if you have a
new enough GTK and have the right packages installed:
wxGTKWebKit - wxPyWiki