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标记的位置?
最合理的方式是通过实例间的引用传递+主动触发重绘,这符合面向对象的设计思路,也能保证数据同步。具体步骤如下:
- 在
Example类中创建Example1的实例,并保存这个实例的引用; - 当滑块滚动时,除了更新文本标签,还要把最新的
VARIABLE值传递给Example1实例; - 在
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场景下几乎是错误的)。
可行的两种写法:
通过实例对象引用访问:如果你的程序中只有一个
Example实例,可以在全局或其他作用域中保存这个实例的引用,然后通过实例名访问:# 假设在程序入口创建了Example实例 app = wx.App() main_frame = Example(None) app.MainLoop() # 在OnSliderScroll中(如果能访问到main_frame) main_frame.txt1.SetLabel(str(VARIABLE))但在
OnSliderScroll方法内部,self本身就是当前的Example实例,所以用self是最直接、最符合规范的写法。将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
相关产品推荐
相关产品推荐

