我试图通过从tkinter.Button
对象派生一个 toggle 按钮类。为此,我使用this StackOverflow答案和these代码示例。
问题是,只有在我两次单击按钮之后,我才能从按钮获得所需的切换行为;前两次单击,不会执行self.config(relief="sunken")
。我尝试使用this答案中的command
关键字参数示例,并且从一开始就有效。
import tkinter as tk
class ToggleButton(tk.Button):
def __init__(self, parent=None, toggle_text="Toggled", toggle_bg_color="green", **kwargs):
tk.Button.__init__(self, parent, **kwargs)
self.toggled = False
self.default_bg_color = self['bg']
self.default_text = self["text"]
self.toggle_bg_color = toggle_bg_color
self.toggle_text = toggle_text
self.bind("<Button-1>", self.toggle, add="+")
def toggle(self, *args):
if self["relief"] == "sunken":
self["bg"] = self.default_bg_color
self["text"] = self.default_text
self.config(relief="raised")
# self["relief"] = "raised"
self.toggled = False
else:
self["bg"] = self.toggle_bg_color
self["text"] = self.toggle_text
# self["relief"] = "sunken"
self.config(relief="sunken")
self.toggled = True
def button_placeholder():
print("TO BE IMPLEMENTED")
root = tk.Tk()
button = ToggleButton(parent=root,
toggle_text="ON", toggle_bg_color="green",
text="OFF", command=button_placeholder)
button.pack()
root.mainloop()
在前两次单击按钮后,发生预期的行为。但是,如果用户将注意力集中在另一个窗口上(例如,通过最小化tkinter窗口),然后又返回,则前两次单击仍不会导致所需的行为。
能不能解释一下?如果没有,有人可以提供一种解决方案,使我在切换按钮时具有一致的行为吗?
有关我的系统的信息
答案 0 :(得分:1)
您似乎遇到的问题是,首次创建按钮时未定义bg
参数;只会在第一次按下按钮时分配一个值。
然后,很难遵循切换逻辑:您有一个self.toggled
布尔值,但您正在测试按钮是否为sunken
以便区分状态...
我重新组织了逻辑,使其更易于遵循;毕竟,切换是从一种状态到另一种状态的二进制变化。因此,我将ON
和OFF
状态的定义放在了类的主体中(分为两个类字典),并且代码在切换时交换了两个配置。
import tkinter as tk
class ToggleButton(tk.Button):
ON_config = {'bg': 'green',
'text': 'button is ON',
'relief': 'sunken',
}
OFF_config = {'bg': 'white',
'text': 'button is OFF',
'relief': 'raised',
}
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.toggled = False
self.config = self.OFF_config
self.config_button()
self.bind("<Button-1>", self.toggle)
def toggle(self, *args):
if self.toggled: # True = ON --> toggle to OFF
self.config = self.OFF_config
else:
self.config = self.ON_config
self.toggled = not self.toggled
return self.config_button()
def config_button(self):
self['bg'] = self.config['bg']
self['text'] = self.config['text']
self['relief'] = self.config['relief']
return "break"
def __str__(self):
return f"{self['text']}, {self['bg']}, {self['relief']}"
def button_placeholder():
print('toggling now!')
if __name__ == '__main__':
root = tk.Tk()
button = ToggleButton(root)
button.pack()
root.mainloop()
修复了按钮方面的问题,使用tk.Label
可以模仿所需的行为:
import tkinter as tk
class ToggleButtonLBL(tk.Label):
ON_config = {'bg': 'green',
'text': 'button is ON',
'relief': 'sunken',
}
OFF_config = {'bg': 'white',
'text': 'button is OFF',
'relief': 'raised',
}
def __init__(self, parent, *args, command=None, **kwargs):
super().__init__(parent, *args, **kwargs)
self.toggled = False
self.config = self.OFF_config
self.config_button()
self.bind("<Button-1>", self._toggle_helper)
self.bind("<ButtonRelease-1>", self._toggle)
self.command = command
def _toggle_helper(self, *args):
return 'break'
def _toggle(self, dummy_event):
self.toggle()
self.cmd()
def toggle(self, *args):
if self.toggled: # True = ON --> toggle to OFF
self.config = self.OFF_config
else:
self.config = self.ON_config
self.toggled = not self.toggled
self.config_button()
return 'break'
def config_button(self):
self['bg'] = self.config['bg']
self['text'] = self.config['text']
self['relief'] = self.config['relief']
return "break"
def __str__(self):
return f"{self['text']}, {self['bg']}, {self['relief']}"
def cmd(self):
self.command()
def button_placeholder():
print('toggling now!')
if __name__ == '__main__':
root = tk.Tk()
button = ToggleButtonLBL(root, command=button_placeholder)
button.pack()
root.mainloop()