python tkinter Button控件上的图标或文字的变化

实现目标

点击按钮,实现属性的变化,根据状态的不同做区分操作

效果图

实现方式-1

import tkinter as tk

def click1():
    global flag_pic
    flag_pic = not flag_pic
    if flag_pic:
        btn_1['image']=pic_2
    else:
        btn_1['image']=pic_1
    root.update()
 
def click2():
    global flag_text
    flag_text = not flag_text
    if flag_text:
        btn_2['text'] = 'Hello'
    else:
        btn_2['text'] = 'Hi'
    root.update()

flag_text = True
flag_pic = True
root = tk.Tk()
pic_1 = tk.PhotoImage(file='pic/play.png')
pic_2 = tk.PhotoImage(file='pic/pause.png')
btn_1 = tk.Button(root,image=pic_2,command=click1)
btn_1.pack()
btn_2 = tk.Button(root,text='Hello',command=click2)
btn_2.pack()
root.mainloop()

评注

评注-1

这里使用到了[tk.PhotoImage],需要注意的是:

You must keep a reference to the image object in your Python program, either by storing it in a global variable, or by attaching it to another object.

Note: When a PhotoImage object is garbage-collected by Python (e.g. when you return from a function which stored an image in a local variable), the image is cleared even if it’s being displayed by a Tkinter widget.

To avoid this, the program must keep an extra reference to the image object. A simple way to do this is to assign the image to a widget attribute, like this:

label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()

声明 pic_1对象时,必须保持对这个Image对象的引用,如通过全局变量的方式或者类对象属性的方式,否则会出现错误,如按钮控件无法点击且为白板等情况

评注-2

按钮对象不支持“.”的方式调用,即使使用却不报错,如下面的代码,不生效也不报错

def click2():
    global flag_text
    flag_text = not flag_text
    if flag_text:
        btn_2.text = 'Hello'
    else:
        btn_2.text = 'Hi'
    root.update()

 

实现方式-2

这种方式是一种投机取巧的方式,但却可以让我们加以发挥到其他情况的使用上。

import tkinter as tk

def click():
    global flag  
    if flag:
        btn_2.pack_forget()
        btn_1.pack()
    else:
        btn_1.pack_forget()
        btn_2.pack()
    flag = not flag
    root.update()
    
flag = True
root = tk.Tk()
pic_1 = tk.PhotoImage(file='pic/play.png')
pic_2 = tk.PhotoImage(file='pic/pause.png')
btn_1 = tk.Button(root,image=pic_2,command=click)
btn_2 = tk.Button(root,image=pic_1,command=click)
btn_2.pack()
root.mainloop()

评注

我们可以看到,上面这个代码虽然实现了“按钮图标切换”,但本质上是实现了两个按钮,两个按钮交互显现。

这里运用到了【pack_forget()函数】,如果说【pack】是古代女子出门抛头露面,那么【pack_forget】则是躲入深闺不见客,女子本身还存在(区别于【destroy】方法),但并没被世人所见。
如果我们使用【destroy】,那么我们每次岂不是都要新建一个一样的对象。

About 【pack_forget 】:Removes the widget from its current manager. The widget is not destroyed, and can be displayed again by pack or any other manager.

 实际上,tkinter的pack布局方式有【pack_forget】,grid布局方式也有它的【grid_forget】,使用pack与pack_forget的方式很容易露马脚,比如下面的情况:

import tkinter as tk

def click():
    ...
    #与上例相同
    
flag = True
root = tk.Tk()
pic_1 = tk.PhotoImage(file='pic/play.png')
pic_2 = tk.PhotoImage(file='pic/pause.png')
btn_1 = tk.Button(root,image=pic_2,command=click)
btn_2 = tk.Button(root,image=pic_1,command=click)
tk.Button(root,text='Hello').pack()
btn_2.pack()
tk.Button(root,text='World').pack()
tk.Button(root,text='Find').pack()
root.mainloop()

效果图

 

 位置变化,原因大致与pack布局是一种顺序堆叠的方式,后面才pack的控件自然就放在后面的位置了。解决这个问题的办法,是采用grid布局方式,如果每个控件要出现的位置是可以限定的,那么就不需要遵循顺序了。

import tkinter as tk

def click():
    global flag  
    if flag:
        btn_2.grid_forget()
        btn_1.grid(row=0,column=1)
    else:
        btn_1.grid_forget()
        btn_2.grid(row=0,column=1)
    flag = not flag
    root.update()
    
flag = True
root = tk.Tk()
pic_1 = tk.PhotoImage(file='pic/play.png')
pic_2 = tk.PhotoImage(file='pic/pause.png')
btn_1 = tk.Button(root,image=pic_2,command=click)
btn_2 = tk.Button(root,image=pic_1,command=click)
tk.Button(root,text='Hello').grid(row=0,column=0)
btn_2.grid(row=0,column=1)
tk.Button(root,text='World').grid(row=0,column=2)
tk.Button(root,text='Find').grid(row=0,column=3)
root.mainloop()

效果图

 

 当然了,使用这种方式来实现按钮图标的切换是一种很鸡贼的方法,之所以花篇幅描述,则是觉得【pack_forget】、【grid_forget】的运用,对于用tkinter来做简单GUI程序有所帮助。

比如,通过运用这种方式,我们可以实现下面的效果,而不需要重载这个Frame,或者每次都生成展示歌曲列表的【listbox】对象,进而做大量的【listbox.insert】步骤,只需要将这个女孩子从深闺中请出来,而不是又重新培养一个这样的女孩子:

 

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值