虽然我认为 Bryan 的回答更简单并且完全解决了问题,但您可以通过绑定解决“可点击性”问题(我没有遇到第二个问题,所以我的回答没有解决它)。
这个想法是绑定鼠标点击框架来触发按钮点击并恢复通常的按钮行为。在下面的示例中,我绑定了<ButtonPress-1> 和<ButtonRelease-1> 以查看按钮浮雕效果。我还绑定了<Enter> 和<Leave> 来实现鼠标悬停时的按钮颜色变化。
from Tkinter import *
master = Tk()
buttons = {}
def press(clicked):
print clicked
def frame_enter(redframe, blueframe):
redframe.configure(background='coral1')
blueframe.configure(background='royalblue1')
def frame_leave(redframe, blueframe):
redframe.configure(background='red')
blueframe.configure(background='blue')
def on_press(event, button):
button.event_generate('<ButtonPress-1>', x=event.x, y=event.y)
def on_release(event, button):
button.event_generate('<ButtonRelease-1>', x=event.x, y=event.y)
for i in range(1,7):
button_name = 'button '+str(i)
buttons[i] = Button(master, text=button_name, command=lambda method=button_name:press(method))
buttons[i].grid(row=0, column=i-1, padx=15)
buttons[i].update()
tot_x = buttons[i].winfo_width()
tot_y = buttons[i].winfo_height()
redframe = Frame(buttons[i], width=tot_x/6, background='red')
blueframe = Frame(buttons[i], width=tot_x/6*5, background='blue')
redframe.place(x=0, y=0, relheight=1)
blueframe.place(relx=1./6, y=0, relheight=1)
redframe.bind('<ButtonPress-1>', lambda e, b=buttons[i]: on_press(e, b))
blueframe.bind('<ButtonPress-1>', lambda e, b=buttons[i]: on_press(e, b))
redframe.bind('<ButtonRelease-1>', lambda e, b=buttons[i]: on_release(e, b))
blueframe.bind('<ButtonRelease-1>', lambda e, b=buttons[i]: on_release(e, b))
redframe.bind('<Enter>', lambda e, rf=redframe, bf=blueframe: frame_enter(rf, bf))
blueframe.bind('<Enter>', lambda e, rf=redframe, bf=blueframe: frame_enter(rf, bf))
redframe.bind('<Leave>', lambda e, rf=redframe, bf=blueframe: frame_leave(rf, bf))
blueframe.bind('<Leave>', lambda e, rf=redframe, bf=blueframe: frame_leave(rf, bf))
master.mainloop()
编辑:不需要保留按钮,它们可以用框架代替。这样就不用place了,把彩框装进去就行了:
from Tkinter import *
master = Tk()
buttons = {}
def press(clicked):
print clicked
def frame_enter(redframe, blueframe):
redframe.configure(background='coral1')
blueframe.configure(background='royalblue1')
def frame_leave(redframe, blueframe):
redframe.configure(background='red')
blueframe.configure(background='blue')
def on_press(event, widget):
widget.configure(relief='sunken') # mimic button's relief effect on click
def on_release(event, widget, text):
widget.configure(relief='raised') # mimic button's relief effect on click
press(text)
for i in range(1,7):
button_name = 'button '+ str(i)
buttons[i] = Frame(master, relief='raised', width=78, height=24, bd=2)
buttons[i].grid(row=0, column=i-1, padx=15)
buttons[i].update_idletasks()
tot_x = buttons[i].winfo_width()
tot_y = buttons[i].winfo_height()
redframe = Frame(buttons[i], width=tot_x/6, height=tot_y, background='red')
blueframe = Frame(buttons[i], width=tot_x/6*5, height=tot_y, background='blue')
redframe.pack(side='left')
blueframe.pack(side='left')
redframe.bind('<ButtonPress-1>', lambda e, b=buttons[i]: on_press(e, b))
blueframe.bind('<ButtonPress-1>', lambda e, b=buttons[i]: on_press(e, b))
redframe.bind('<ButtonRelease-1>', lambda e, b=buttons[i], t=button_name: on_release(e, b, t))
blueframe.bind('<ButtonRelease-1>', lambda e, b=buttons[i], t=button_name: on_release(e, b, t))
redframe.bind('<Enter>', lambda e, rf=redframe, bf=blueframe: frame_enter(rf, bf))
blueframe.bind('<Enter>', lambda e, rf=redframe, bf=blueframe: frame_enter(rf, bf))
redframe.bind('<Leave>', lambda e, rf=redframe, bf=blueframe: frame_leave(rf, bf))
blueframe.bind('<Leave>', lambda e, rf=redframe, bf=blueframe: frame_leave(rf, bf))