我正在 Tkinter、Python 中使用按钮。
问题是,当我单击一个按钮时,按钮的文本会抖动。这可能是这个小部件的默认行为,我不知道如何禁用它并使其静态。
我假设您的意思是当您单击按钮时浮雕从凸起变为凹陷。
这是我在 http://wiki.tcl.tk/1048 上找到的内容(单击“显示讨论”即可查看):
不幸的是,单击时使用的浮雕是硬编码的(如 'sunken'),所以你不能在不破解 Tk 的情况下为每个小部件配置它 按钮绑定的内部结构。
因此,解决此问题的最简单方法是始终使按钮看起来凹陷
MyButton = Tkinter.Button(
self.frame,
text = "Foobar",
command = self.foobar,
relief=Tkinter.SUNKEN
)
这样做的缺点是它可能会使按钮看起来没有反应。
您还可以使用按钮以外的小部件作为可点击项目(由 Joel Cornett 建议)。这是一个简单的示例,其中标签用作按钮:
import Tkinter
class main:
def __init__(self,root):
# make a label with some space around the text
self.lbl1 = Tkinter.Label(root,
width = 16, height = 4,
text = "Foobar")
self.lbl1.pack()
# Call a function when lbl1 is clicked
# <Button-1> means a left mouse button click
self.lbl1.bind("<Button-1>", self.yadda)
self.lbl1.bind("<Enter>", self.green)
self.lbl1.bind("<Leave>", self.red)
def yadda(self, event):
self.lbl1.config(text="Clicked!")
def green(self, event):
self.lbl1.config(bg="green")
def red(self,event):
self.lbl1.config(bg="red")
if __name__ == "__main__":
root = Tkinter.Tk()
main(root)
root.mainloop()
为了保留它作为参考,我采用了 @Junuxx 代码并对其进行了修改,以创建我认为是 Ttk 按钮的直接替代品。我重新配置了一些选项,使其行为尽可能接近 Ttk 按钮:
from tkinter import Event
from tkinter.ttk import Widget, Label
class FlatButton(Label):
'''This label behaves like a button, without click animation
By default the label has no borders
It can be used like a button, with the same initial values. Please consider
however that this is still a label for styling.
Took inspiration from https://stackoverflow.com/a/10674950/3368201
Options comparison:
- Some options are common to both and behave the same: class, compound,
cursor, image, style, text, textvariable, underline, width
- Some are common to both, but behave differently:
- takefocus -> it has a different default value; managed in __init__
(point #2)
- Some are only present in BUTTON:
- command -> it is managed in a more "pythonic" way using a global
wrapper and special cases in bind, unbind and configure.
It is also managed in __init__ (point #1)
- Some are only present in LABEL; these values can be redefined in the
__init__ call or through configure,: anchor (default value changed to
'center'), background, font, foreground, justify, padding, relief,
wraplength, borderwidth
'''
@staticmethod
def overriden_default_states() -> dict[str, Any]:
'''Provide default states for properties
These values will be set when not passed in __init__
Returns:
dict[str, Any]: The dictionary with the properties and their value
'''
return {
'takefocus': True,
'anchor': 'center'
}
def __init__(self, parent: Widget = None, **kw):
'''Construct a Ttk Button-like widget with the provided parent.
This is in fact a Label, with some button behavior implemented inside.
See class description for more info on what is allowed
Args:
parent (Widget, optional): The parent widget. Defaults to None.
'''
# 1) Manually manage command
self._command = kw.pop('command', None)
# 2) If not provided, set overriden_default_states
for k, v in self.overriden_default_states().items():
if k not in kw:
kw[k] = v
# Create the button
super().__init__(parent, **kw)
# All events in _click_binds will trigger a command
self._click_binds = {'<Button-1>': [], '<space>': []}
# Bind them to the special wrapper function
for seq in self._click_binds.keys():
super().bind(seq, lambda ev, seq=seq: self.click_event(seq, ev))
# ------------------------
# Command management
def click_event(self, sequence: str, event: Event):
'''The _btn_pressed_sequence was triggered
Args:
event (Event): The event data
'''
for b in self._click_binds.get(sequence, []):
b(event)
self.invoke()
def invoke(self) -> Any:
'''If there is a command, call it
If the button is disabled nothing will be done
Returns:
Any: The command return value if it is executed, otherwise None
'''
if self._command and not self.instate(['disabled']):
return self._command()
def bind(self, sequence=None, func=None, add=None):
'''Overriding bind to extract the _btn_pressed_sequence
'''
if sequence in self._click_binds.keys():
if (not func) or (not add):
self._click_binds[sequence].clear()
if func:
self._click_binds[sequence].append(func)
result = '__unsupported__'
else:
result = super().bind(sequence, func, add)
return result
def unbind(self, sequence, funcid=None):
'''Overriding unbind to extract the _btn_pressed_sequence
'''
if sequence in self._click_binds.keys():
self._click_binds[sequence].clear()
else:
super().unbind(sequence, funcid)
def configure(self, cnf=None, **kw):
'''Overriding unbind to extract the command
'''
if 'command' in kw:
self._command = kw.pop('command', None)
return self.configure(cnf, kw)
默认外观是一个平面按钮,但是你可以在构造函数中将其更改为
relief='raised'
,然后将其用作普通按钮:
def command(self):
print("Clicked command!")
def yadda(self, event):
print("Clicked yadda!")
btn = FlatButton(root, text='aaa', relief='raised', command=command)
btn.pack()
btn.bind("<Button-1>", self.yadda)
然后该对象将在启用和禁用状态下正确管理命令和绑定,并且单击时不会移动
与“真实”按钮的区别:
anchor
和 foreground
属性)TLable