在使用 Python Tkinter 开发 GUI 程序时,遇到一个奇怪的问题。当我在 GUI 中添加一个按钮,并将按钮的命令设置为调用某个方法时,第一次按下按钮,程序可以正常运行。但是,当我第二次按下按钮时,程序会报错,提示方法找不到。
- 解决方案
经过一番排查,我发现问题出在变量命名上。在代码中,我使用了相同的变量名来表示两个不同的对象。一个变量名表示数值,另一个变量名表示对象。当我在按钮的命令中调用方法时,程序会根据变量名寻找对应的对象,但是由于变量名相同,程序无法区分是哪个对象的方法,因此报错。
为了解决这个问题,我将变量名进行了区分。对于表示数值的变量,我使用了不同的名称。对于表示对象的变量,我使用了不同的名称。这样,程序就可以正确地区分不同的对象,并且可以正常调用方法。
下面是我修改后的代码:
from Tkinter import *
import ttk
# RGB LED 数值
red_value = 0
green_value = 0
blue_value = 0
# RGB LED 对象
red_led = RGB_LED('Red', 0, 0.0)
green_led = RGB_LED('Green', 1, 0.0)
blue_led = RGB_LED('Blue', 2, 0.0)
def test_pwm_set(channel, intensity):
global red_value, green_value, blue_value
print "Calling test_pwm_set"
if channel == 0:
red_value = intensity
print "Red = " + str(intensity)
elif channel == 1:
green_value = intensity
print "Green = " + str(intensity)
elif channel == 2:
blue_value = intensity
print "Blue = " + str(intensity)
else:
print 'Invalid Channel!'
def set_red_intensity():
intensity = float(red_input.get())
print intensity
print red_led.get_intensity()
red_led.set_intensity(50.0)
def set_green_intensity():
intensity = float(green_input.get())
green_led.set_intensity(intensity)
def set_blue_intensity():
intensity = float(blue_input.get())
blue_led.set_intensity(intensity)
class RGB_LED:
def __init__(self, color, channel, intensity = 0.0):
self.color = color
self.channel = channel
self.intensity = intensity
def get_channel(self):
return self.channel
def get_intensity(self):
return self.intensity
def get_color(self):
return self.color
def set_channel(self, channel):
self.channel = channel
def set_intensity(self, intensity):
self.intensity = intensity
test_pwm_set(self.channel, self.intensity)
def set_color(self, color):
self.color = color
######## set up GUI ##########
root = Tk()
root.title("RGB LED Control")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) #frame fills all of root window
mainframe.columnconfigure(0, weight=1) #tells Tk if root window is resized
mainframe.rowconfigure(0, weight=1) #the frame should take up the extra space
# StringVars
red_input = StringVar()
red_input.set(0.0)
green_input = StringVar()
green_input.set(0.0)
blue_input = StringVar()
blue_input.set(0.0)
red_intensity = StringVar()
green_intensity = StringVar()
blue_intensity = StringVar()
# Entry fields
red_entry = ttk.Entry(mainframe, width=5, textvariable=red_input)
red_entry.grid(column=1, row=2, sticky=(W, E))
green_entry = ttk.Entry(mainframe, width=5, textvariable=green_input)
green_entry.grid(column=2, row=2, sticky=(W, E))
blue_entry = ttk.Entry(mainframe, width=5, textvariable=blue_input)
blue_entry.grid(column=3, row=2, stick=(W, E))
# Labels
ttk.Label(mainframe, textvariable=red_intensity).grid(column=1, row=1, sticky=(W, E))
ttk.Label(mainframe, textvariable=green_intensity).grid(column=2, row=1, sticky=(W, E))
ttk.Label(mainframe, textvariable=blue_intensity).grid(column=3, row=1, sticky=(W, E))
# Buttons
ttk.Button(mainframe, text="Red", command= lambda: set_red_intensity()).grid(column=1, row=3, sticky=(W, E))
ttk.Button(mainframe, text="Green", command= lambda: set_green_intensity()).grid(column=2, row=3, sticky=(W, E))
ttk.Button(mainframe, text="Blue", command= lambda: set_blue_intensity()).grid(column=3, row=3, sticky=(W, E))
root.mainloop()
经过修改后,代码可以正常运行。第一次按下按钮时,程序会调用相应的方法,并正确地设置 RGB LED 的强度。第二次按下按钮时,程序也会正常调用方法,并正确地设置 RGB LED 的强度。