Hello,

I am a wxpython newbie and would like some help on using custom classes to create and change widgets.

I have a program with 2 classes, each of which creates a panel with widgets. These panels are then added to the main frame of an application.

In one class I create a statictext label (dalabel). In another class I create a button (dabutton). I want to change the statictext label created in the first class with the button-click event created in the second class.

The following code produces the button-click error ' dalabel is not defined '.

#!/usr/bin/python


import wx
import time


class MakePanel1(wx.Panel):
    def __init__(self, Parent, *args, **kwargs):
        wx.Panel.__init__(self, Parent, *args, **kwargs)
        
        self.dalabel = wx.StaticText(self, -1, "   panel 1 label   ")
        self.bs1 = wx.BoxSizer(wx.HORIZONTAL)
        self.bs1.Add(self.dalabel,0,wx.ALL,20)
        self.SetSizer(self.bs1)


class MakePanel2(wx.Panel):
    def __init__(self, Parent, *args, **kwargs):
        wx.Panel.__init__(self, Parent, *args, **kwargs)
        
        self.dabutton = wx.Button(self, label="panel 2 button") 
        self.dabutton.Bind(wx.EVT_BUTTON, self.daclick )
        self.bs2 = wx.BoxSizer(wx.HORIZONTAL)
        self.bs2.Add(self.dabutton,0,wx.ALL,20)
        self.SetSizer(self.bs2)

    def daclick(self, event=None):
        dalabel.SetLabel(str(time.time()))


class DisFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.Panel1 = MakePanel1(self)
        self.Panel2 = MakePanel2(self)

        bs = wx.BoxSizer(wx.VERTICAL)
        bs.Add(self.Panel1,1,wx.EXPAND);
        bs.Add(self.Panel2,1,wx.EXPAND);

        self.SetSizer(bs)
        self.Fit()


if __name__ == '__main__':
    app = wx.App()
    frame = DisFrame(None)
    frame.Show()
    app.MainLoop()

What is the proper syntax for referencing the statictext object created in the MakePanel1 class whilst within the MakePanel2 class?

I would like to change the statictext label of the MakePanel1 class with the button-click event of the MakePanel2 class, but do not know how to reference this statictext object in order to change its properties.

I prefer to have the statictext and button widgets created in separate classes. Any help will be appreciated.

Thank you.

Dani AI

Generated

Both of the simple approaches already suggested in the thread — referencing the other panel through the frame (as pointed out) or keeping a parent reference inside the button panel (as @faulkner suggested) — are valid. For clearer, safer code it’s better to let the panel that owns the label expose a tiny API (for example a set_label method) and either pass that method as a callback into the button panel or pass the panel instance itself. That keeps each class responsible for its own widgets instead of poking directly at another panel’s internals.

Example pattern (keeps responsibilities explicit and is easy to read):

class LabelPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self._label = wx.StaticText(self, label="panel 1 label")
        s = wx.BoxSizer(wx.HORIZONTAL)
        s.Add(self._label, 0, wx.ALL, 10)
        self.SetSizer(s)

    def set_label(self, text):
        self._label.SetLabel(text)
        self.Layout()

class ButtonPanel(wx.Panel):
    def __init__(self, parent, update_callback):
        wx.Panel.__init__(self, parent)
        self._update = update_callback
        btn = wx.Button(self, label="panel 2 button")
        btn.Bind(wx.EVT_BUTTON, self._on_click)
        s = wx.BoxSizer(wx.HORIZONTAL)
        s.Add(btn, 0, wx.ALL, 10)
        self.SetSizer(s)

    def _on_click(self, event):
        import time
        self._update("updated: {}".format(time.time()))

Wire them in the frame by giving the button panel a callable it can call (for example panel_with_label.set_label). This is more maintainable than reaching into panel.Panel1._label from elsewhere. Additional tips: if a SetLabel change doesn’t appear immediately, call the panel’s Layout() or Refresh() after setting the label. If updates come from a worker thread, post the change to the GUI thread (e.g. wx.CallAfter(panel.set_label, text)). For larger apps consider wx.lib.pubsub or custom events to decouple components. Pick the style that reads best later, but prefer a small public method or callback over directly manipulating another panel’s internals.

Recommended Answers

All 4 Replies

You have to reference dalabel via DisFrame --> frame --> Panel1, so it ends up frame.Panel1.dalabel.SetLabel(str(time.time()))

Thanks to vegaseat. The suggested syntax works well.

Another solution offered by faulkner of python-forum.org was to add the following code:

class MakePanel2(...):
     def __init__(...):
         self.parent = Parent
         ...
     def daclick(...):
         self.parent.Panel1.dalabel.SetLabel(...)

Both solutions achieve the desired goal of changing the statictext label, but since I am a newbie, I am not in a position to determine if one approach is 'better' than the other.

Thanks again to vegaseat.

Just a matter of style! Pick the style that you think is easier to read or understand, particularly a few months from now.

Ok.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.