How to reference attributes of other classes?

Hi, all


from threading import Thread
import wx

class MainWindow(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="sylphlker")
        self.Center()
        self.panel = wx.Panel(self, wx.ID_ANY)            
        self.k1  = wx.TextCtrl(self.panel, -1, "F1", size=(45,25), style=wx.TE_READONLY)


      
def HotKey():
    hotkey = MainWindow.k1.GetValue()
    print(hotkey)
if __name__ == '__main__':
    app = wx.App()
    frame = MainWindow()
    frame.Show()  
    app.MainLoop()
    p = Thread(target=HotKey, daemon=True)
    p.start()
    p.join()

Exception in thread Thread-1:
Traceback (most recent call last):
File “C:\Python37\lib\threading.py”, line 926, in _bootstrap_inner
self.run()
File “C:\Python37\lib\threading.py”, line 870, in run
self._target(*self._args, **self._kwargs)
File “test3.py”, line 15, in HotKey
hotkey = MainWindow.k1.GetValue()
AttributeError: type object ‘MainWindow’ has no attribute ‘k1’

Why does this happen? How to reference attributes of other classes?

You have two issues:

  • first, as mentioned in a reply to your previous post, wx.App gets destroyed when its MainLoop terminates
  • second, you were trying to GetValue from the class (MainWindow) rather than from an object instance of that class (frame). The TextCtrl k1 is added in init, rather than at the class level, so it doesn’t exist until an instance is created.

To fix these issues: start your thread before app.MainLoop, and get the value of “hotkey” from “frame” instead of “MainWindow”. I still don’t know what you’re working toward, but this will print “F1” at the console and it won’t blow up, so there’s a start.

from threading import Thread
import wx

class MainWindow(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="sylphlker")
        self.Center()
        self.panel = wx.Panel(self, wx.ID_ANY)
        self.k1  = wx.TextCtrl(self.panel, -1, "F1", size=(45,25), style=wx.TE_READONLY)
def HotKey():
    hotkey = frame.k1.GetValue()
    print(hotkey)
if __name__ == '__main__':
    app = wx.App()
    frame = MainWindow()
    frame.Show()
    p = Thread(target=HotKey)
    p.start()
    #p.join() - this locks up the GUI thread
    app.MainLoop()

Tank you very much, a thread can quote attributes of the wx.frame(the main process), but the child process can not(in the other post i asked, as you mentioned), because they run in different memory spaces. Do i get the truth? I need to learn more and thanks predecessors.

Yes - a Thread shares the same memory space, while a Process doesn’t. However, your previous code (using Process) also had the same two issues I addressed here.

In your program so far, you’re only getting the current value of a read-only attribute from the GUI, and that doesn’t present any blocking issues (unless you join() the thread, which is why I commented that out.) As you make things more complex, you WILL run into blocking issues. It’s a little old, but I still strongly suggest that you work through the “Non-blocking GUI” article from the wxPyWiki; it will make things a LOT clearer.

Thanks again, I felt the warmth, i am Chinese, i’m a layman, but I love programming.

1 Like