【问题标题】:Color a Tkinter button in multiple colors用多种颜色为 Tkinter 按钮着色
【发布时间】:2018-12-22 00:08:50
【问题描述】:

我试图在 Tkinter 中的一个按钮上添加多种颜色。这就是我想出的:

from Tkinter import *
master = Tk()
buttons = {}

def press(clicked):
    print clicked
    return
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)

master.mainloop()

问题在于它使按钮几乎不能点击,因为框架会以某种方式干扰按钮的“可点击性”。当光标放在它们的位置时,彩色框架也会突然消失。

有没有办法让这些框架停留在按钮上并使它们不停止点击?

【问题讨论】:

    标签: python python-2.7 tkinter


    【解决方案1】:

    虽然我认为 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)) 
    

    【讨论】:

    • 这样的东西可以用来创建可点击的框架,甚至不用按钮,对吧?这也对我有用。因为对我来说,带有代码的彩色框架在第一次单击后光标远离它们时消失,并在光标位于它们上时重新出现。
    【解决方案2】:

    可以说,最简单的方法可能是创建具有所需颜色的图像,然后将按钮中的图像与文本一起使用。

    【讨论】:

    • 是的,在尝试了许多看起来最好的不同方法之后。但是我现在对 PIL 有一个不同的问题,我将为此创建一个新问题。
    猜你喜欢
    • 2019-10-03
    • 2020-04-21
    • 2018-06-10
    • 2016-11-07
    • 2019-12-20
    • 1970-01-01
    • 2015-03-11
    • 2019-06-18
    • 1970-01-01
    相关资源
    最近更新 更多