原文链接:http://www.juzicode.com/archives/1293
这篇教程到目前为止都是在命令行下运行的,命令行下一片黑乎乎的,运行程序也只能用到键盘,说句流行的话叫“用户体验不好”,今天我们就来聊聊“体验更好” 的图形界面。在Python里PyQT,wxPython,tkinter等等都可以用来做用户界面,今天我们先来聊聊tkinter,源于tcl语言,是tcl做的用户界面接口,后来被集成到Python中作为一个标准库。
1 一个简单的例子
使用tkinter构建图形界面,首先要导入tkinter模块,初始化一个Tk()实例,然后执行这个实例的mainloop()方法,就可以实现一个窗口:
from tkinter import *
root =Tk()
root.mainloop()
运行该py文件,看到的界面是这样的:
继续使用title()方法增加窗口标题,geometry()方法控制窗口大小,注意 geometry()方法的入参是x字符分隔的窗口宽高值:
from tkinter import *
root =Tk()
root.title('桔子code')
root.geometry('500x300')
root.mainloop()
运行该文件,看到的界面效果是这样的:
为了后续方便扩展,我们可以创建一个自定义的class,下面的功能等同于前述创建窗口的功能:
from tkinter import *
class GuiWindow():
def __init__(self):
self.root=Tk()
self.root.title('桔子code')
self.root.geometry('500x300')
if __name__ == "__main__":
gw = GuiWindow()
gw.root.mainloop()
2、添加菜单栏
使用Menu()创建菜单栏对象 menu_bar ,并且将这个菜单栏 menu_bar 对象绑定到Tk()对象上,接着创建一级菜单 menu_file ,并将这个一级菜单绑定到 menu_bar ;再在一级菜单menu_file上用 add_command 创建二级菜单:
from tkinter import *
class GuiWindow():
def __init__(self):
self.root=Tk()
self.root.title('桔子code')
self.root.geometry('500x300')
#创建菜单栏
self.menu_bar = Menu(self.root)
self.root['menu'] = self.menu_bar
#创建一级菜单
self.menu_file = Menu(self.menu_bar, tearoff=0)
self.menu_bar.add_cascade(label="文件", menu=self.menu_file)
#创建二级菜单
self.menu_file.add_command(label='保存', command = None) #command对应要执行的动作
self.menu_file.add_command(label='退出', command = self.root.quit)
if __name__ == "__main__":
gw = GuiWindow()
gw.root.mainloop()
3、添加frame
如果需要增加按钮,文本框,单选框,需要先创建一个Frame()实例,在这个Frame()实例中绑定这些按钮、文本框等控件。Frame()实例创建时,同时绑定到Tk()的root实例中:
#添加fame
self.frame_base = ttk.Frame(self.root,width =20, height = 30)
self.frame_base.pack(side=TOP,fill=BOTH,padx = 10)
这里我们都使用pack方法进行布局,pack方法不需要太多关心控制的具体位置和大小,只需要关注各种控件的相对位置。pack方法中side参数表示排列方式,TOP表示从上往下开始布局,fill参数表示是否扩充控件对象,padx或者pady表示控件在x或者y方向的填充空白像素大小。
在self.frame_base内部就可以继续添加按钮或者文本框等实例,在self.frame_base内部创建的控件,仍然以pack方法进行布局,下面的例子添加了Button()、Entry()等3个实例,在self.frame_base内部以side=Left方式布局,注意这时候的布局和self.frame_base的布局方法是不冲突,它们并不是在同一个层级上,:
#添加frame
self.frame_base = ttk.Frame(self.root,width =20, height = 30)
self.frame_base.pack(side=TOP,fill=BOTH,padx = 10)
self.select_file_button = Button(self.frame_base,width =12,text='选择文件',command= None)
self.select_file_button.pack(side=LEFT, padx=5, pady=2) # fill=BOTH,
self.select_file_entry = Entry(self.frame_base, text='选择文件:', width=60)
self.select_file_entry.pack(side=LEFT, padx=5, pady=5,expand=1,fill=BOTH) #
self.select_file_clear_button = Button(self.frame_base,width =12,text='清除状态栏',command= None)
self.select_file_clear_button.pack(side=LEFT, padx=5, pady=2) # fill=BOTH,
当使用expand=1和fill=BOTH后,对应的控件会跟随窗口大小自动扩展,一般可以用在Entry实例上:
3.1 在frame中添加frame
#frame中添加frame
self.frame_status = ttk.Frame(self.root)
self.frame_status.pack(side=TOP,fill=BOTH,padx = 10)
self.frame_status_sub1 = ttk.Frame(self.frame_status) ##frame中添加下级frame
self.frame_status_sub1.pack(side=TOP, fill=BOTH,padx = 10,pady = 10 )
self.quit_button = Button(self.frame_status_sub1,text='退出',width = 10,padx=10,command=None)
self.quit_button.pack(side = RIGHT)
self.status_clear_button = Button(self.frame_status_sub1,text='清除',width = 10,padx=10,command=None)
self.status_clear_button.pack(side = RIGHT)
self.text_status = ScrolledText(self.frame_status,wrap = WORD)
self.text_status.pack(side = BOTTOM ,fill=BOTH, )
Frame()实例可以看做是一个”容器”,可以用来存放Button、Entry、ScrolledText等实例,也可以用来存放下级Frame。
4、添加Tab控件
使用 ttk.Notebook( )可以创建一个tab控件实例,然后使用该实例的add方法就可以将新创建的frame实例添加进来,在frame实例内部也可以添加 Button、Entry、ScrolledText 、Radio等实例。
#添加tab控件
self.tab_all = ttk.Notebook(self.root)
self.tab_all.pack(expand=1, fill=BOTH)
self.tab_1 = Frame(self.tab_all)
self.tab_all.add(self.tab_1, text=' tab1 ')
self.tab_2 = Frame(self.tab_all)
self.tab_all.add(self.tab_2, text=' tab2 ')
self.tab_1_radio_var = IntVar()
self.tab_1_radio_method1 = Radiobutton(self.tab_1, text="方法1", variable=self.tab_1_radio_var, value=1, command=None)
self.tab_1_radio_method1.pack(side = BOTTOM) #grid( row=1 ,column=0)
self.tab_1_radio_method2 = Radiobutton(self.tab_1, text="方法2", variable=self.tab_1_radio_var, value=2, command=None)
self.tab_1_radio_method2.pack(side = BOTTOM) #grid(row=2,column=0, )
效果如下图所示:
5、绑定函数
在前面的例子中,控件对应的动作函数都是暂时用command=None代替,相应的按钮,单选框等都需要和相应的函数绑定,点击相应的控件才会触发动作,比如这个例子中选择文件按钮:
self.select_file_button = Button(self.frame_base,width =12,text='选择文件',command= None)
可以自定义一个方法 self. select_file_button_command,用command=self.select_file_button_command,这样在点击选择文件按钮的时候哦,就会调用 self.select_file_button_command 方法,该方法实现弹框选择某个文件的功能:
self.select_file_button = Button(self.frame_base,width =12,text='选择文件',command= self.select_file_button_command)
def select_file_button_command(self):
self.selected_file = filedialog.askopenfilename()
print('selected_file:',self.selected_file)
self.select_file_entry.delete(0, END)
self.select_file_entry.insert(0, self.selected_file)
6、控件常用方法、属性
ScrolledText
insert(END,’ABC’): 在最后插入字符串
see(END) :下拉到最后
update():更新窗口
delete(0.0,END):删除所有内容,0.0表示从第0行,第0列开始,
Entry
insert(0, str) 从0开始插入str字符串,一般配合delete方法先删除再写入
delete(0, END) 表示从开始0到结束END都删除
get() 获取entry中的内容,返回字符串结果
Radio
Radio中的变量先用radio_var = IntVar()新建一个实例,然后在Radio的定义中,用参数variable= radio_var ,value= 1(或者其他值)绑定这个实例,
self.tab_1_radio_var = IntVar()
self.tab_1_radio_method1 = Radiobutton(self.tab_1, text="方法1", variable=self.tab_1_radio_var, value=1, command=None)