2

This is one of those questions that is really frustrating for me to ask because I'm sure the answer is out there, I just haven't been able to word the searches correctly. Basically I am new to GUI programming (done a decent amount of embedded C/C++) and learning wxPython to start out.

I'm making an app to read and write to a config file. So I have a StaticText to display the name of the parameter to be read/written, a TextCtrl to display the value and allow user input, and then a Get button and a Set button. I'll call all of these together a "group" of widgets. For this app obviously this group will be repeated several times. Rather than write and maintain all that code by hand, I thought it would be easier to simply have a list of the config parameters I want to be able to edit, and then iterate through the list and generate an instance of this "group" of widgets for each item in the list. I made it work except for one thing: I had to bind all of the Get buttons to the same function. Same thing with the Set buttons. Is there any way from within those functions to know which Get or Set button was pushed, and thus which parameter to find and edit in the config file? I'm sure there's a way to do this with parent or IDs or something but I'm just too new to OOP.

0

3 Answers 3

2

I assume that the get button reads the parameter value from the config file and displays the value.

Why do you need one get button for each parameter? I would have just one get button for tham all. When the user clicks the get button, every parameter is read from the file and all the displays are updated.

A similar approach for the set button. One set button for them all - when the button is pressed every parameter that has a new value entered is updated in the config file. Parameters where the user has not entered a new value remain with their previous values.

This scheme is easier to code, and easier for the user also.

However, I really suggest you look at the wxPropertyGrid widget. This has the potential to make your life a lot easier! Here's a screenshot showing one in action

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Don't have enough rep yet but when I do I'll be back (:
1

In your button's event handler, you can do something like this:

btn = event.GetEventObject()
btn.GetId()
btn.GetName()

Then you just use an If statement to decide what to do based on whatever info you want to use. Note: you can set the button's name when you create the button like this:

setBtn = wx.Button(self, label="Set", name="SetX")

You might find this article on wxPython and ConfigObj helpful too: http://www.blog.pythonlibrary.org/2010/01/17/configobj-wxpython-geek-happiness/

2 Comments

Followup question: After I've identified which button was clicked, how can I access the corresponding text box to read/write the value? Is there a way to store something like a list of pointers to the text boxes I'm using then loop through that list and compare the names of each text box until I find the right one?
I don't think the button's support client data, so you'd be better off creating a dict and using the button's unique name to map to the text control. Something like self.myDict = {"firstBtn":firstTxt}. Then you could just use the name of the button to map to the text control.
0

You can derive your own class from the wx.Button and add one or more attributes to it to make the button remember any information you want.

You can use this stored information during a callback function call. Something like:

import wx

L = [("1", "One"), ("2", "Two"), ("3", "Three")]

# =====================================================================
class MemoryButton(wx.Button):
    def __init__(self, memory, *args, **kwargs):
        wx.Button.__init__(self, *args, **kwargs)
        self.memory = memory

# =====================================================================
class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.panel = wx.Panel(self)
        self.buttons = []
        for description in L:
            button = MemoryButton(memory=description[1], parent=self.panel,
                                  label=description[0])
            button.Bind(wx.EVT_BUTTON, self.OnMemoryButton)
            self.buttons.append(button)

        self.sizer = wx.BoxSizer()
        for button in self.buttons:
            self.sizer.Add(button)

        self.panel.SetSizerAndFit(self.sizer)  
        self.Show()

    # -----------------------------------------------------------------
    def OnMemoryButton(self, e):
        print("Clicked '%s'" % e.GetEventObject().memory)

# =====================================================================
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()

or alternatively:

import wx

L = [("1", "One"), ("2", "Two"), ("3", "Three")]

# =====================================================================
class MemoryButton(wx.Button):
    def __init__(self, memory, *args, **kwargs):
        wx.Button.__init__(self, *args, **kwargs)
        self.memory = memory

    def OnButton(self, e):
        print("Clicked '%s'" % self.memory)

# =====================================================================
class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.panel = wx.Panel(self)
        self.buttons = []
        for description in L:
            button = MemoryButton(memory=description[1], parent=self.panel,
                                  label=description[0])
            button.Bind(wx.EVT_BUTTON, button.OnButton)
            self.buttons.append(button)

        self.sizer = wx.BoxSizer()
        for button in self.buttons:
            self.sizer.Add(button)

        self.panel.SetSizerAndFit(self.sizer)  
        self.Show()

# =====================================================================
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.