You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python类间变量传递及wxPython代码语句修正技术咨询

嘿,咱们来逐个解决这两个wxPython问题。先看看你的代码(我顺便修复了几个语法错误,比如缺失的闭合括号和未定义的变量):

class Example(wx.Frame):
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)
        self.InitUI()
    def InitUI(self):
        pnl = wx.Panel(self)
        sld = wx.Slider(pnl, value=0, minValue=0, maxValue=200, pos=(30, 20), size=(650, 15), style=wx.SL_HORIZONTAL)
        sld1 = wx.Slider(pnl, value=0, minValue=0, maxValue=360, pos=(30, 50), size=(650, 15), style=wx.SL_HORIZONTAL)
        sld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
        sld1.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
        self.txt1 = wx.StaticText(pnl, label='0', pos=(250, 120))
        self.txt2 = wx.StaticText(pnl, label='0', pos=(10, 50))
        self.SetSize((700, 200))
        self.SetTitle('ROBO ARM')
        self.Centre()
        self.Show(True)
    def OnSliderScroll(self, e):
        id_slider = e.GetId()
        obj = e.GetEventObject()
        VARIABLE = obj.GetValue()
        # 修复:原代码val未定义,改为VARIABLE
        tty = str(VARIABLE)+str(id_slider)
        # 修复:添加缺失的闭合括号
        self.txt1.SetLabel(str(VARIABLE))

class Example1(wx.Frame):
    def __init__(self, parent, title):
        super(Example1, self).__init__(parent, title=title, size=(350, 280))
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Centre()
        self.Show()
    def OnPaint(self, e):
        dc = wx.PaintDC(self)
        dc.SetPen(wx.Pen('#d4d4d4'))
        dc.SetBrush(wx.Brush('#c56c00'))
        dc.DrawRectangle(10, 7, 90, **VARIABLE NEEDS HERE**)

问题1:如何将Example类中的VARIABLE传递到Example1类中dc.DrawRectangle标记的位置?

最合理的方式是通过实例间的引用传递+主动触发重绘,这符合面向对象的设计思路,也能保证数据同步。具体步骤如下:

  1. 在Example类中创建Example1的实例,并保存这个实例的引用;
  2. 当滑块滚动时,除了更新文本标签,还要把最新的VARIABLE值传递给Example1实例;
  3. 在Example1类中添加一个属性存储这个值,并提供更新方法触发重绘。

修改后的完整代码示例:

import wx

class Example(wx.Frame):
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)
        self.InitUI()
        # 创建Example1实例,将当前Example作为父窗口,保存引用
        self.arm_preview = Example1(self, title="Robo Arm Preview")

    def InitUI(self):
        pnl = wx.Panel(self)
        sld = wx.Slider(pnl, value=0, minValue=0, maxValue=200, pos=(30, 20), size=(650, 15), style=wx.SL_HORIZONTAL)
        sld1 = wx.Slider(pnl, value=0, minValue=0, maxValue=360, pos=(30, 50), size=(650, 15), style=wx.SL_HORIZONTAL)
        sld.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
        sld1.Bind(wx.EVT_SCROLL, self.OnSliderScroll)
        self.txt1 = wx.StaticText(pnl, label='0', pos=(250, 120))
        self.txt2 = wx.StaticText(pnl, label='0', pos=(10, 50))
        self.SetSize((700, 200))
        self.SetTitle('ROBO ARM CONTROL')
        self.Centre()
        self.Show(True)

    def OnSliderScroll(self, e):
        obj = e.GetEventObject()
        VARIABLE = obj.GetValue()
        self.txt1.SetLabel(str(VARIABLE))
        # 将最新值传递给Example1,并触发重绘
        self.arm_preview.update_rect_param(VARIABLE)

class Example1(wx.Frame):
    def __init__(self, parent, title):
        super(Example1, self).__init__(parent, title=title, size=(350, 280))
        # 初始化存储参数的属性,默认值为90(原代码中的初始宽度)
        self.rect_width = 90
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Centre()
        self.Show()

    def update_rect_param(self, new_width):
        self.rect_width = new_width
        # 触发重绘事件,让OnPaint重新执行
        self.Refresh()

    def OnPaint(self, e):
        dc = wx.PaintDC(self)
        dc.SetPen(wx.Pen('#d4d4d4'))
        dc.SetBrush(wx.Brush('#c56c00'))
        # 使用传递过来的参数绘制矩形
        dc.DrawRectangle(10, 7, self.rect_width, 50)  # 这里高度设为50,你可以按需调整

if __name__ == '__main__':
    app = wx.App()
    Example(None)
    app.MainLoop()

如果不想让Example1作为Example的子窗口,也可以用wxPython的自定义事件来传递数据,但对于这种简单场景,上面的方式更直接易懂。


问题2:能否将语句self.txt1.SetLabel(str(VARIABLE))中的self改为类似Example.InitUI的写法?

首先要明确:Example.InitUI是类的方法引用,但txt1是Example实例的属性(不是类属性),所以不能直接用Example.txt1(除非你把txt1改成类属性,但这会导致所有Example实例共享同一个文本控件,这在GUI场景下几乎是错误的)。

可行的两种写法:

  1. 通过实例对象引用访问:如果你的程序中只有一个Example实例,可以在全局或其他作用域中保存这个实例的引用,然后通过实例名访问:

    # 假设在程序入口创建了Example实例
    app = wx.App()
    main_frame = Example(None)
    app.MainLoop()
    
    # 在OnSliderScroll中(如果能访问到main_frame)
    main_frame.txt1.SetLabel(str(VARIABLE))
    

    但在OnSliderScroll方法内部,self本身就是当前的Example实例,所以用self是最直接、最符合规范的写法。

  2. 将txt1改为类属性(不推荐):如果你确定整个程序只会有一个Example实例,可以把txt1定义为类属性:

    class Example(wx.Frame):
        # 定义类属性txt1
        txt1 = None
        def __init__(self, *args, **kw):
            super(Example, self).__init__(*args, **kw)
            self.InitUI()
        def InitUI(self):
            pnl = wx.Panel(self)
            # ...其他代码...
            # 给类属性赋值
            Example.txt1 = wx.StaticText(pnl, label='0', pos=(250, 120))
            # ...其他代码...
    

    然后在OnSliderScroll中就可以写成:

    Example.txt1.SetLabel(str(VARIABLE))
    

    但这种方式会导致多个Example实例互相覆盖txt1的值,所以强烈不推荐。

总结:除非有特殊需求,否则原代码中的self.txt1.SetLabel(str(VARIABLE))(已修复语法错误)是最优写法。


内容的提问来源于stack exchange,提问作者Alek Szczęsnowicz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:52:35