【问题标题】:Python, A class within a class, how to access variables from the upper classPython,类中的一个类,如何从上层访问变量
【发布时间】:2016-08-28 10:57:51
【问题描述】:

我有 Qt Gui 类处理所有变量(p1p2)调整滑块和东西。在这个类中,我有一个 OSC 监听器类,它应该监听来自另一个设备的触发信号和一个变量p3,并使用这些参数来触发声音和图形。但我无法在侦听器类中访问p1p2。这是一个例子:

class Ptsgui(QtGui.QMainWindow):
    def __init__(self):
        super(Ptsgui, self).__init__()
        self.p1, self.p2, self.data = 0, 0, np.zeros(10)
        self.initUI()

    class OscListener(object):
        def __init__(self, data):
            self.listenerData = data
            self.receive_address = '127.0.0.1', 7000
        def do_stuff_listener(self, addr, tags, stuff, source):
            print self.p1
            print self.p2
            self.p3 = stuff[0]
            trigger_sound_and_graphic(self.p1, self.p2, self.p3)

        def spawn(self):
            self.receiveServer = OSC.OSCServer(self.receive_address)
            self.receiveServer.addDefaultHandlers()
            self.receiveServer.addMsgHandler("/trigger", self.do_stuff_listener()
            self.emorating_oscServer = threading.Thread(target=self.receiveServer.serve_forever)
            self.emorating_oscServer.start()

    def initUI():
        """ 
        Some sliders setup for change the p1 & p2
        """
        self.setGeometry(50, 50, 1050, 650)
        mainlayout = QtGui.QVBoxLayout()
        self.widget = QtGui.QWidget()
        self.widget.setLayout(mainlayout)
        self.listener = OscListener(data = self.data)
        self.show()

所以在这里我希望oscListener() 可以直接访问self.p1self.p2。显然我不能这样做,因为self.p1 的“自我”指的是OscListener,而不是Ptsguido_stuff_listener 也在单独的线程中,是否仍然可以访问 self.p1self.p2

最终,我希望用户能够通过 GUI 来控制参数值。并且每次通过OSC接收到一个触发信号,都会产生一个新的图形和声音。请告知是否有更好的方法来做到这一点。

【问题讨论】:

    标签: python class pyqt subclass osc


    【解决方案1】:

    你想要达到的目标可以这样做:

    class Ptsgui(QtGui.QMainWindow):
        def __init__(self):
            super(Ptsgui, self).__init__()
            self.p1, self.p2, self.data = 0, 0, np.zeros(10)
            self.initUI()
    
        def initUI():
            """
            Some sliders setup for change the p1 & p2
            """
            self.setGeometry(50, 50, 1050, 650)
            mainlayout = QtGui.QVBoxLayout()
            self.widget = QtGui.QWidget()
            self.widget.setLayout(mainlayout)
            self.listener = OscListener(gui=self, data=self.data)
            self.show()
    
    
    class OscListener(object):
        def __init__(self, gui, data):
            self.gui = gui
            self.listenerData = data
            self.receive_address = '127.0.0.1', 7000
        def do_stuff_listener(self, addr, tags, stuff, source):
            print self.gui.p1
            print self.gui.p2
            self.p3 = stuff[0]
            trigger_sound_and_graphic(self.gui.p1, self.gui.p2, self.gui.p3)
    
        def spawn(self):
            self.receiveServer = OSC.OSCServer(self.receive_address)
            self.receiveServer.addDefaultHandlers()
            self.receiveServer.addMsgHandler("/trigger", self.do_stuff_listener()
            self.emorating_oscServer = threading.Thread(target=self.receiveServer.serve_forever)
            self.emorating_oscServer.start()
    

    请注意,您的代码示例中的类嵌套是不需要的。

    另外,在我看来,您试图实现的目标是不正确的。代码非常耦合。考虑将PtsguiOscListener 解耦。检查Observer pattern 以获得一些灵感。

    【讨论】:

    • 谢谢。这正是我所需要的。那么这是否意味着它将 Ptsgui 的指针传递给 OscListener?那样的话,我可以直接在 OscListener 中改变 p1 和 p2 的值吗?
    • 是的,正确的。你可以这样做,但正如我提到的,代码是非常耦合的。如果您想要更好的解决方案,请尝试使用一些设计模式将其解耦,例如观察者模式。
    【解决方案2】:

    您可以像这样将Ptsgui 传递给OscListener

    class Ptsgui(QtGui.QMainWindow):
        def __init__(self):
            super(Ptsgui, self).__init__()
            self.p1, self.p2, self.data = 0, 0, np.zeros(10)
            self.initUI()
    
        class OscListener(object):
            def __init__(self, cls, data):
                self.parent = cls
                self.listenerData = data
                self.receive_address = '127.0.0.1', 7000
            def do_stuff_listener(self, addr, tags, stuff, source):
                print self.parent.p1 # Access it.
                print self.parent.p2
                self.p3 = stuff[0]
                trigger_sound_and_graphic(self.p1, self.p2, self.p3)
    
            def spawn(self):
                self.receiveServer = OSC.OSCServer(self.receive_address)
                self.receiveServer.addDefaultHandlers()
                self.receiveServer.addMsgHandler("/trigger", self.do_stuff_listener()
                self.emorating_oscServer = threading.Thread(target=self.receiveServer.serve_forever)
                self.emorating_oscServer.start()
    
        def initUI():
            """ 
            Some sliders setup for change the p1 & p2
            """
            self.setGeometry(50, 50, 1050, 650)
            mainlayout = QtGui.QVBoxLayout()
            self.widget = QtGui.QWidget()
            self.widget.setLayout(mainlayout)
            self.listener = OscListener(cls=self, data = self.data) # Pass it here
            self.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-14
      • 2020-10-18
      • 1970-01-01
      • 2011-10-22
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      相关资源
      最近更新 更多