Python-tkinter

按钮等其他内容见微信收藏笔记部分。

http://effbot.org/tkinterbook/button.htm

其他常用组件:ScrolledText、Labelframe

固定窗口大小:root.resizable(0,0),第一个0表示固定宽,第二个0表示固定高,非0表示不固定。布尔值就好。


Label

 1 from tkinter import *
 2 
 3 
 4 class Application(Frame):
 5     def __init__(self, master):
 6         super().__init__(master)
 7         self.label2 = None
 8         self.create_widget()
 9         self.pack()
10 
11     def create_widget(self):
12         label = Label(self, text='标签一\n还能换行', width=9, height=2,
13                       bg='red', fg='blue', font=('黑体', 30))  # 还有‘宋体’等。如果是字符width、height单位是字符(字母数字1个字符,汉字算2个字符)
14         label.pack()
15 
16         # global img    # 也可以在此处创建图片对象,只是不符合PEP8
17         # img = PhotoImage(file='label.gif') # 若不设为global会导致局部变量调完后销毁,看不到效果
18         self.label2 = Label(self, image=img, width=50, height=30)  # 如果是图像width、height单位是像素
19         self.label2.pack()
20 
21         label3 = Label(self, text='随便写点', borderwidth=1, relief='solid', justify='right')
22         label3.pack()
23 
24 
25 root = Tk()
26 root.title('窗口标题')
27 root.geometry('300x200-500-400')
28 img = PhotoImage(file='label.gif')
29 app = Application(root)
30 root.mainloop()

 Option的3种设置方式:

 1 from tkinter import *
 2 
 3 
 4 class App(Frame):
 5     def __init__(self, master):
 6         super().__init__(master)
 7         self.create_widgets()
 8         self.pack()
 9 
10     def create_widgets(self):
11         label = Label(self, dict(text='标签文本', border=1), justify='right', width=20,
12                       font=('黑体', 20, 'bold'))  # option设置方式一:命名参数  也可写成justify=RIGHT
13         label['bg'] = 'red'  # option设置方式二:字典索引
14         label.config(fg='blue', height=3)  # option设置方式三:config方法
15         label.pack()
16 
17 
18 root = Tk()
19 root.title('窗口标题')
20 root.geometry('300x200+500+400')
21 app = App(root)
22 root.mainloop()

 Entry和密码显示样式设置:

 1 from tkinter import *
 2 
 3 
 4 class App(Frame):
 5     def __init__(self, master):
 6         super().__init__(master)
 7         self.pack()
 8         self.create_widgets()
 9 
10     def create_widgets(self):
11         lable_username = Label(self, text='用户名')
12         lable_username.pack()
13 
14         username = StringVar()  # username变量会改变Entry中的值,Entry中的值变化会改变username值,互相影响。
15         entry_username = Entry(self, textvariable=username)
16         entry_username.pack()
17         username.set('admin')
18 
19         lable_pwd = Label(self, text='密码')
20         lable_pwd.pack()
21 
22         pwd = StringVar()
23         entry_pwd = Entry(self, textvariable=pwd, show='*')
24         entry_pwd.pack()
25 
26         btn = Button(self, text='确定', command=lambda: self.f(username, pwd))
27         btn.pack()
28 
29     def f(self, username, pwd):
30         print('用户名:', username.get())
31         print('密码:', pwd.get())
32 
33 
34 master = Tk()
35 app = App(master)
36 master.mainloop()

 Text组件:有好多方法和知识点

 1 # Text组件
 2 from tkinter import *
 3 import webbrowser
 4 
 5 
 6 class App(Frame):
 7     def __init__(self, master):
 8         super().__init__(master)
 9         self.pack()
10         self.create_widgets()
11 
12     def create_widgets(self):
13         self.w = Text(self, width=50, height=15, bg='gray')
14         self.w.pack()
15 
16         self.w.insert(1.0, '0123456789\nabcdefghijklmnopqrstuvwxyz')  # 1.0表示第1行第0列,行从1开始计,列从0开始计
17         self.w.insert(2.4, '随便写点啥')
18 
19         Button(self, text='重复插入文本', command=self.insertText).pack(side=LEFT)
20         Button(self, text='返回文本', command=self.returnText).pack(side=LEFT)
21         Button(self, text='添加图片文本', command=self.addImg).pack(side=LEFT)
22         Button(self, text='添加组件', command=self.addWidget).pack(side=LEFT)
23         Button(self, text='通过tag精确控制文本', command=self.testTag).pack(side=LEFT)
24 
25     def insertText(self):
26         self.w.insert(INSERT, '在光标处插入')  # INSERT表示在光标处插入
27         self.w.insert(END, '在最后插入')  # END表示在末尾插入
28 
29     def returnText(self):
30         print(self.w.get(1.3, 2.3))  # 打印从第1行第3列开始到第2行第5列开始的字符,包头不包尾,即不包括第2行第5列那个字符
31         self.w.insert(1.5, '新字')
32         print(self.w.get(1.0, END))  # 打印所有字符
33 
34     def addImg(self):
35         # 写法一:
36         # global photo #不能用局部变量,不然图片不显示,因为方法调完后局部变量对象就会销毁
37         # photo=PhotoImage(file='label.gif')
38         # self.w.image_create(END, image=photo)
39 
40         # 写法二:
41         self.photo = PhotoImage(file='label.gif')
42         self.w.image_create(END, image=self.photo)
43 
44     def addWidget(self):
45         self.w.window_create(INSERT, window=Button(self.w, text='按钮'))
46 
47     def testTag(self):
48         self.w.delete(1.0, END)
49         self.w.insert(INSERT, '好好学习,天天向上\n0987654321sdljflds\nslfjlajfksdfowef\nsfslfjdskjlfs')
50         self.w.tag_add('good', 1.0, 1.9)
51         self.w.tag_config('good', background='red', foreground='blue')
52 
53         self.w.tag_add('sogo', 4.0, 4.2)
54         self.w.tag_config('sogo', underline=True)
55         self.w.tag_bind('sogo', '<Button-1>', self.webshow)
56 
57     def webshow(self, e):
58         webbrowser.open('sogo.com')
59 
60 
61 root = Tk()
62 app = App(root)
63 root.mainloop()

 Radiobutton

 1 from tkinter import *
 2 from tkinter import messagebox
 3 
 4 class App(Frame):
 5     def __init__(self, master):
 6         super().__init__(master)
 7         self.pack()
 8         self.create_widgets()
 9 
10     def create_widgets(self):
11         self.v_bool = BooleanVar()
12         self.v_bool.set(True)
13         self.r_bool1 = Radiobutton(self, text='', value=True, variable=self.v_bool)
14         self.r_bool2 = Radiobutton(self, text='', value=False, variable=self.v_bool)
15         self.r_bool1.pack(side=LEFT);self.r_bool2.pack(side=LEFT)
16 
17         self.v_int = IntVar()
18         self.v_int.set(0)
19         self.r_int1 = Radiobutton(self, text='', value=0, variable=self.v_int)
20         self.r_int2 = Radiobutton(self, text='', value=1, variable=self.v_int)
21         self.r_int1.pack(side='left');self.r_int2.pack(side=LEFT)
22 
23         self.v_double = DoubleVar()
24         self.v_double.set(1.1)
25         self.r_double1 = Radiobutton(self, text='1点1', value=1.1, variable=self.v_double)
26         self.r_double2 = Radiobutton(self, text='2点2', value=2.2, variable=self.v_double)
27         self.r_double1.pack(side=LEFT);self.r_double2.pack(side=LEFT)
28 
29         self.v_string = StringVar()
30         self.v_string.set('M')
31         self.r_string1 = Radiobutton(self, text='', value='M', variable=self.v_string)
32         self.r_stirng2 = Radiobutton(self, text='', value='F', variable=self.v_string)
33         self.r_string1.pack(side=LEFT);self.r_stirng2.pack(side=LEFT)
34 
35         Button(self, text='确定', command=self.confirm).pack()
36 
37     def confirm(self):
38         info = ''.join(['v_bool=', str(self.v_bool.get()), '\nv_int=', str(self.v_int.get()), '\nv_double=',
39                         str(self.v_double.get()), '\nv_string=', self.v_string.get()])
40         messagebox.showinfo('信息', info)
41 
42 root = Tk()
43 app = App(root)
44 root.mainloop()

 Checkbutton

 1 from tkinter import *
 2 from tkinter import messagebox
 3 
 4 
 5 class App(Frame):
 6     def __init__(self, master):
 7         super().__init__(master)
 8         self.pack()
 9         self.create_widgets()
10 
11     def create_widgets(self):
12         self.v_bool = BooleanVar()
13         print('默认值:BooleanVar()=', self.v_bool.get())
14         self.c_bool = Checkbutton(self, text='布尔值', variable=self.v_bool, onvalue=True,
15                                   offvalue=False)  # 一开始通过默认值判断onvalue是否符合
16         self.c_bool.pack(side='left')
17 
18         self.v_int = IntVar()
19         print('默认值:IntVar()=', self.v_int.get())
20         self.c_int = Checkbutton(self, text='整数', variable=self.v_int, onvalue=1, offvalue=0)  # 一开始无论啥值都不勾选
21         self.c_int.pack(side=LEFT)
22 
23         self.v_double = DoubleVar()
24         print('默认值:DoubleVar()=', self.v_double.get())
25         self.c_double = Checkbutton(self, text='浮点数', variable=self.v_double, onvalue=1.1, offvalue=0.0)  # 一开始无论啥值都不勾选
26         self.c_double.pack(side=LEFT)
27 
28         self.v_string = StringVar()
29         print('默认值:StringVar()=', self.v_string.get())
30         self.c_string = Checkbutton(self, text='字符串', variable=self.v_string, onvalue='a',
31                                     offvalue='')  # 一开始通过判断offvalue的值确定是否勾选,若一开始offvalue!='',则勾选
32         self.c_string.pack(side=LEFT)
33 
34         Button(self, text='确定', command=self.confirm).pack()
35 
36     def confirm(self):
37         info = ''.join(['c_bool:', str(self.v_bool.get()), '\nc_int:', str(self.v_int.get()), '\nc_double:',
38                         str(self.v_double.get()), '\nc_string:', self.v_string.get()])
39         messagebox.showinfo('结果', info)
40 
41 
42 root = Tk()
43 app = App(root)
44 root = mainloop()

 Canvas

 1 from tkinter import *
 2 import random
 3 
 4 
 5 class App(Frame):
 6     def __init__(self, master):
 7         super().__init__(master)
 8         self.pack()
 9         self.create_widgets()
10 
11     def create_widgets(self):
12         self.canvas = Canvas(self, width=500, height=300, bg='green')
13         self.canvas.pack()
14 
15         line = self.canvas.create_line(15, 15, 35, 28, 45, 66)  # 连续3个坐标点,形成折线
16         rect = self.canvas.create_rectangle(60, 60, 150, 150)  # 矩形
17         oval = self.canvas.create_oval(60, 60, 150, 150)  # 椭圆
18 
19         # 方法一:对象属性,即self.photo
20         self.photo = PhotoImage(file='label.gif')
21         self.canvas.create_image(180, 90, image=self.photo)
22         # 方法二:全局变量:global photo ,但不建议用全局变量,原则:少用全局变量,全局变量比局部变量慢,而且风险大
23         # global photo
24         # photo = PhotoImage(file='label.gif')
25         # self.canvas.create_image(180, 90, image=photo)
26         # 用局部变量不行,因为方法调完后局部变量对象会自动销毁,图片无法显示
27         # photo = PhotoImage(file='label.gif')
28         # self.canvas.create_image(180, 90, image=photo)
29 
30         Button(self, text='画多个矩形', command=self.drawMultiRect).pack()
31 
32     def drawMultiRect(self):
33         for i in range(10):
34             x1 = random.randrange(int(self.canvas['width']) / 2)
35             y1 = random.randrange(int(self.canvas['height']) / 2)
36             x2 = x1 + random.randrange(int(self.canvas['width']) / 2)
37             y2 = y1 + random.randrange(int(self.canvas['height']) / 2)
38             self.canvas.create_rectangle(x1, y1, x2, y2)
39 
40 
41 root = Tk()
42 root.title('画布')
43 root.geometry('600x400+300-200')
44 app = App(root)
45 root.mainloop()

 grid布局

 1 from tkinter import *
 2 
 3 
 4 class App(Frame):
 5     def __init__(self, master):
 6         super().__init__(master)
 7         self.pack()
 8         self.create_widgets()
 9 
10     def create_widgets(self):
11         self.label_username = Label(self, text='用户名')
12         self.label_username.grid(row=0, column=0)
13         self.entry_username = Entry(self).grid(row=0, column=1)
14         self.label_tips = Label(self, text='用户名为手机号').grid(row=0, column=2)
15 
16         Label(self, text='密码').grid(row=1, column=0)
17         Entry(self, show='#').grid(row=1, column=1)
18 
19         Button(self, text='登录').grid(row=2, column=1, sticky=EW)  # EW为左右两端对齐,两端拉长
20         Button(self, text='取消').grid(row=2, column=2, sticky=E)
21 
22 
23 root = Tk()
24 root.title('grid布局')
25 root.geometry('600x400+300-200')
26 app = App(root)
27 root.mainloop()

 计算器界面:知识点:enumeraterowspan跨行columnspan跨列,padx横向间距,pady竖向间距

 

 1 from tkinter import *
 2 
 3 class App(Frame):
 4     def __init__(self, master):
 5         super().__init__(master)
 6         self.pack()
 7         self.createWidgets()
 8 
 9     def createWidgets(self):
10         btnTexts = (('MC', 'M+', 'M-', 'MR'), ('C', '±', '÷', '×'), (7, 8, 9, '-'), (4, 5, 6, '+'), (1, 2, 3, '='), (0, '.'))
11         Entry(self).grid(row=0, column=0, columnspan=4, padx=3, pady=3)  # columnspan跨列,padx横向间距,pady竖向间距
12         for rindex, r in enumerate(btnTexts):
13             for cindex, c in enumerate(r):
14                 if c == '=':
15                     Button(self, text=c).grid(row=rindex + 1, column=cindex, rowspan=2,sticky=NSEW)  # rowspan跨行。sticky=NSEW,其中NSEW顺序不能随便写
16                 elif c == 0:
17                     Button(self, text=c).grid(row=rindex + 1, column=cindex, columnspan=2, sticky=NSEW)
18                 elif c == '.':
19                     Button(self, text=c).grid(row=rindex + 1, column=cindex + 1, sticky=NSEW)
20                 else:
21                     Button(self, text=c).grid(row=rindex + 1, column=cindex, sticky=NSEW)
22 
23 root = Tk()
24 app = App(root)
25 root.mainloop()

 pack布局

 1 from tkinter import *
 2 
 3 root = Tk()
 4 root.geometry('700x220') #第3、4个参数,与屏幕左、上的距离可省
 5 f1 = Frame(root);f1.pack()  # 和f1=Frame(root).pack()写法效果不一样
 6 f2 = Frame(root);f2.pack()  # 和f2=Frame(root).pack()写法效果不一样
 7 
 8 btnTexts = ('天龙八部', '雪山飞狐', '笑傲江湖', '神雕侠侣', '飞狐外传')
 9 for i in btnTexts:
10     Button(f1, text=i).pack(side=LEFT, padx=10,pady=5)
11 
12 for i in range(10):
13     Label(f2, width=5, height=10, borderwidth=1, relief='solid',
14           bg='black' if i % 2 == 0 else 'white').pack(side='left', padx=2)
15 root.mainloop()

 place()布局

 1 from tkinter import *
 2 
 3 root=Tk();root.geometry('500x300')
 4 
 5 f1=Frame(root,width=200,height=200,bg='green')
 6 f1.place(x=30,y=30)#绝对定位x,y
 7 
 8 #relx和x同时存在时先通过relx相对定位,再通过x偏移,即x在有relx时的作用不是绝对定位,成了偏移量
 9 #relx、rely、relwidth、relheigth取值范围[0,1],相对父组件,relx=0最左,relx=1最右,rely=0最顶,rely=1最底
10 #relwidth=0.5父组件宽度一半,relheight=0.5父组件高度一半
11 Button(root,text='好好学习').place(relx=.2,x=100,y=20,relwidth=.2,relheight=.5)
12 Button(f1,text='天天向上').place(relx=.4,rely=.8)
13 Button(f1,text='勤学精专').place(relx=.3,rely=.2)
14 root.mainloop()

 扑克牌出牌效果

 1 from tkinter import *
 2 
 3 class App(Frame):
 4     def __init__(self,master):
 5         super().__init__(master)
 6         self.pack()
 7         self.createWidgets()
 8 
 9     def createWidgets(self):
10         # self.img=PhotoImage(file='pai/pai7.gif')
11         # self.pai=Label(self.master,image=self.img)#此处self不显示图片,要写成self.master才行
12         # self.pai.place(x=10,y=50)
13 
14         self.imgs=[PhotoImage(file='pai/pai'+str(i)+'.gif') for i in range(7,10)]
15         self.pais=[Label(self.master,image=self.imgs[i]) for i in range(3)]
16         for i in range(3):self.pais[i].place(x=10+i*50,y=50)
17 
18         self.pais[2].bind_class('Label','<1>',self.play)#pais[0]、pais[1]、pais[2]随便写哪个,都一样,为什么?因为绑定了类事件bind_class('Label')吗?
19         # self.pais[1].bind_class('Label','<Button-1>',self.play)# <1>和<Button-1>效果一样
20 
21     def play(self,e):
22         print(e.widget.winfo_geometry())# 获取宽高坐标
23         print(e.widget.winfo_y()) #获取坐标y
24         if e.widget.winfo_y()==50:
25             e.widget.place(y=30) #设置坐标y
26         else:
27             e.widget.place(y=50)
28 
29 root=Tk()
30 root.geometry('800x500')
31 app=App(root)
32 root.mainloop()

 组件绑定事件,消息处理:widget.bind(event,handler)

 1 #coding='utf-8'
 2 #coding=utf-8
 3 #以上两种写法都行
 4 from tkinter import *
 5 
 6 root=Tk();root.geometry('600x400')
 7 c=Canvas(root,width=200,height=200,bg='green')
 8 c.pack()
 9 
10 def mouseTest(e):
11     print('鼠标左键单击位置(相对于父容器):{},{}'.format(e.x,e.y))
12     print('鼠标左键单击位置(相对于屏幕):{},{}'.format(e.x_root,e.y_root))
13     print('事件绑定的组件:{}'.format(e.widget))
14 
15 def testDrag(e):
16     c.create_oval(e.x,e.y,e.x+1,e.y+1)
17 
18 def keyboardTest(e):
19     print('键的keycode:{},键的char:{},键的keysym:{}'.format(e.keycode,e.char,e.keysym))
20 
21 def press_a_test(e):
22     print('press a')
23 
24 def release_a_test(e):
25     print('release a')
26 
27 c.bind('<1>',mouseTest) #单击:1鼠标左键 2鼠标中键 3鼠标右键
28 
29 c.bind('<B1-Motion>',testDrag) #Motion移动:1鼠标左键 2鼠标中键 3鼠标右键
30 
31 root.bind('<KeyPress>',keyboardTest)
32 root.bind('<KeyPress-a>',press_a_test) #小写a 。大写A无效
33 root.bind('<KeyRelease-a>',release_a_test)
34 root.mainloop()

 使用lambda绑定带参数的函数:

 1 from tkinter import *
 2 root=Tk();
 3 def f1():
 4     print('不涉及获取事件event对象')
 5 
 6 def f2(a,b):
 7     print(a+b)
 8 
 9 Button(root,text='绑定f1',command=f1).pack()
10 Button(root,text='绑定f2',command=lambda :f2(2,3)).pack()
11 
12 root.mainloop()

 OptionMenu

 1 from tkinter import *
 2 
 3 root = Tk();
 4 root.geometry('250x150')
 5 
 6 v = StringVar() #v = StringVar(root) 参数root可有可无
 7 v.set('天龙八部')
 8 # optionMenu=OptionMenu(root,v,'红楼梦','水浒传','三国演义','西游记',width=10).pack() #这种写法会报错
 9 optionMenu=OptionMenu(root,v,'红楼梦','水浒传','三国演义','西游记')
10 optionMenu.pack()
11 optionMenu['width']=10#会报错,为啥??
12 
13 # optionMenu = OptionMenu(root, v, '红楼梦', '水浒传', '三国演义', '西游记').pack()
14 # print(optionMenu)  # None
15 # optionMenu['width'] = 10  # TypeError: 'NoneType' object does not support item assignment
16 
17 def f():
18     print('选择了:',v.get())
19     v.set('四大名著') # 可直接修改optionMenu值
20 
21 Button(root,text='确定',command=f).pack()
22 root.mainloop()

 Scale

 1 from tkinter import *
 2 
 3 root = Tk();root.geometry('500x200')
 4 
 5 def f(v):
 6     print('滑块值:', v)
 7     newFont = ('宋体', v, 'bold')
 8     label.config(font=newFont)
 9 
10 # 这有个坑:from_有个下划线,容易忽略。
11 # 会自动把scale的值当参数传给函数,orient默认竖直,tickinterval刻度显示间距
12 scale = Scale(root, from_=10, to=50, tickinterval=5, length=200, orient=HORIZONTAL, command=f)
13 scale.pack()
14 
15 label = Label(root, text='好好学习', width=9, height=1, bg='red', fg='yellow')
16 label.pack()
17 
18 root.mainloop()

 选择颜色:colorchooser、askcolor

 1 from tkinter import *
 2 from tkinter.colorchooser import *
 3 
 4 root = Tk();
 5 root.geometry('500x300')
 6 
 7 def f():
 8     color = askcolor(color='yellow', title='选择颜色')  # color='yellow'默认色
 9     print(color)
10     root.config(bg=color[1])
11 
12 Button(root, text='选择背景颜色', command=f).pack()
13 root.mainloop()

 打开文件,获取文件路径:

 1 from tkinter import *
 2 from tkinter.filedialog import *
 3 
 4 root=Tk();root.geometry('500x300')
 5 
 6 def f():
 7     file=askopenfilename(title='上传文件',initialdir='c:',filetypes=[('自定义说明','.txt')])
 8     label['text']=file
 9 
10 Button(root,text='选择文本文件',command=f).pack()
11 label=Label(root,width=50,height=5,bg='pink')
12 label.pack()
13 root.mainloop()

 打开文件,获取文件内容:

 1 from tkinter.filedialog import *
 2 
 3 root=Tk();root.geometry('500x300')
 4 
 5 def f():
 6     with askopenfile(title='上传文件',initialdir='D:',filetypes=[('自定义说明','.txt')]) as file:
 7         label['text']=file.read()
 8 
 9 Button(root,text='选择文本文件内容',command=f).pack()
10 label=Label(root,width=50,height=5,bg='pink')
11 label.pack()
12 root.mainloop()

 简单对话框:tkinter.simpledialog、askinteger、askfloataskstring

 1 from tkinter.simpledialog import * 
 2 
 3 root=Tk()
 4 
 5 def f():
 6     text=askinteger(title='标题',prompt='提示语',initialvalue=10,minvalue=0,maxvalue=100)
 7     # text=askfloat()
 8     # text=askstring()
 9     label['text']=text
10 
11 Button(root,text='输入一个数',command=f).pack()
12 label=Label(root)
13 label.pack()
14 root.mainloop()

 通用消息框

1 from tkinter import *
2 from tkinter.messagebox import *
3 
4 root=Tk()
5 text=showinfo(title='标题',message='提示信息')
6 print(text) # ok
7 # showwarning()
8 # showerror()
9 root.mainloop()

 

 简易记事本:菜单Menu

增加快捷键事件绑定:root.bind('<Control-n>', lambda event:self.newfile())  # 通过bind绑定的都会传事件对象event,所以要用lambda接收参数,self.newfile()为lambda的表达式,可以不使用传进来的事件对象参数。

root.bind('<Control-o>', lambda event:self.openfile())

新建文件:

def newfile(self):

  self.filename=asksavefilename(title='新建文件',initialfile='未命名.txt', filetypes=[('文本文件','*.txt')], defaultextension='.txt')

 1 from tkinter.filedialog import *
 2 
 3 root=Tk();root.geometry('450x350+400+280')
 4 
 5 menubar=Menu(root)#创建主菜单
 6 
 7 menuFile=Menu(menubar)#创建子菜单
 8 menuEdit=Menu(menubar)
 9 menuHelp=Menu(menubar)
10 
11 #将子菜单加入到主菜单栏
12 menubar.add_cascade(label='文件(F)',menu=menuFile)
13 menubar.add_cascade(label='编辑(E)',menu=menuEdit)
14 menubar.add_cascade(label='帮助(H)',menu=menuHelp)
15 
16 def openfile():
17     text.delete(1.0,END)  #还可写成 '1.0','end' 随意
18     with askopenfile(title='打开文件') as f:
19         content=f.read()
20         text.insert(INSERT,content)
21         print(f.name)
22 
23 
24 def savefile():
25     with open('d:/menu.txt','w') as f:
26         content=text.get(1.0,END)
27         f.write(content)
28 
29 #给子菜单添加菜单项
30 menuFile.add_command(label='打开',accelerator='ctrl+o',command=openfile)
31 menuFile.add_command(label='保存',accelerator='ctrl+s',command=savefile)
32 menuFile.add_separator()#添加分割线
33 menuFile.add_command(label='退出',command=quit) #退出随便用exit或quit
34 # menuFile.add_command(label='退出',command=exit)
35 
36 root['menu']=menubar
37 
38 ##############################################################
39 
40 #添加右键:上下文件菜单、快捷菜单
41 def createContextMenu(e):
42     contextBar.post(e.x_root,e.y_root)
43 
44 contextBar=Menu(root)#创建右键菜单(上下文件菜单、快捷菜单)
45 contextBar.add_command(label='另存为...')
46 contextBar.add_command(label='退出应用',command=exit)
47 
48 root.bind('<3>',createContextMenu)
49 
50 
51 text=Text(root,width=50,height=20)
52 text.pack()
53 
54 root.mainloop()

 简易画图小工具:

  1 from tkinter import *
  2 from tkinter.colorchooser import *
  3 
  4 class App(Frame):
  5     def __init__(self,master,fgcolor='#000000'):
  6         super().__init__(master)
  7         self.x=0
  8         self.y=0
  9         self.fgcolor='#ff0000'
 10         self.lastDraw=0 #从1开始的整数,最后绘制的图形的id
 11         self.startDrawFlag=False
 12         self.pack()
 13         self.createWidgets()
 14 
 15     def createWidgets(self):
 16         self.drawPad = Canvas(self, width=900, height=450, bg='black')
 17         self.drawPad.pack()
 18 
 19         start=Button(self,text='开始',name='start')
 20         start.pack(side=LEFT,padx=10)
 21         self.pen=Button(self,text='画笔',name='pen')
 22         self.pen.pack(side=LEFT,padx=10)
 23         rect=Button(self,text='矩形',name='rect')
 24         rect.pack(side=LEFT,padx=10)
 25         clear=Button(self,text='清屏',name='clear')
 26         clear.pack(side=LEFT,padx=10)
 27         erasor=Button(self,text='橡皮擦',name='erasor')
 28         erasor.pack(side=LEFT,padx=10)
 29         self.line=Button(self,text='直线',name='line')
 30         self.line.pack(side=LEFT,padx=10)
 31         lineArrow=Button(self,text='箭头直线',name='lineArrow')
 32         lineArrow.pack(side=LEFT,padx=10)
 33         color=Button(self,text='颜色',name='color')
 34         color.pack(side=LEFT,padx=10)
 35 
 36         # 给所有Button类对象绑定单击鼠标左键事件。此语句导致了按钮没有点击态,未解之谜?
 37         self.pen.bind_class('Button','<1>',self.eventManager)
 38         self.drawPad.bind('<ButtonRelease-1>',self.stopDraw)
 39 
 40         #增加颜色切换快捷键
 41         # self.drawPad.bind('<KeyPress-r>',self.changeColor) # 无效
 42         # self.bind('<KeyPress-r>',self.changeColor) # 无效
 43         self.master.bind('<KeyPress-r>',self.changeColor) # 有效,区分大小写
 44         self.master.bind('<KeyPress-g>',self.changeColor) # 有效
 45         self.master.bind('<KeyPress-b>',self.changeColor) # 有效
 46 
 47     def eventManager(self,e):
 48         name=e.widget.winfo_name()
 49         if name=='line':
 50             self.drawPad.bind('<B1-Motion>',self.myline)
 51         elif name=='lineArrow':
 52             self.drawPad.bind('<B1-Motion>',self.mylineArrow)
 53         elif name=='rect':
 54             self.drawPad.bind('<B1-Motion>',self.myrect)
 55         elif name=='pen':
 56             self.drawPad.bind('<B1-Motion>',self.mypen)
 57         elif name=='erasor':
 58             self.drawPad.bind('<B1-Motion>',self.myerasor)
 59         elif name=='clear':
 60             # self.drawPad.delete('all') # 写法一
 61             self.drawPad.delete(ALL) # 写法二
 62             self.drawPad.delete('ALL') # 这种写法不行
 63         elif name=='color':
 64             self.fgcolor=askcolor(color='yellow',title='选择颜色')[1]
 65 
 66     def startDraw(self,e):
 67         self.drawPad.delete(self.lastDraw)  # 删除鼠标抬起前的所有画线,只保留鼠标抬起前的最后一次画线
 68 
 69         if not self.startDrawFlag:
 70             self.startDrawFlag = True
 71             self.x = e.x
 72             self.y = e.y
 73 
 74     def myline(self,e):
 75         self.startDraw(e)
 76         self.lastDraw=self.drawPad.create_line(self.x,self.y,e.x,e.y,fill=self.fgcolor)
 77         # print(self.lastDraw) #从1开始的整数,最后绘制的图形的id
 78 
 79     def mylineArrow(self,e):
 80         self.startDraw(e)
 81         self.lastDraw=self.drawPad.create_line(self.x,self.y,e.x,e.y,arrow=LAST,fill=self.fgcolor)
 82 
 83     def myrect(self,e):
 84         self.startDraw(e)
 85         # self.lastDraw=self.drawPad.create_rectangle(self.x,self.y,e.x,e.y,fill=self.bgcolor) # 填充
 86         self.lastDraw=self.drawPad.create_rectangle(self.x,self.y,e.x,e.y,outline=self.fgcolor)
 87 
 88     def mypen(self,e):
 89         self.startDraw(e)
 90         self.drawPad.create_line(self.x,self.y,e.x,e.y,fill=self.fgcolor)
 91         self.x=e.x
 92         self.y=e.y
 93 
 94     def myerasor(self,e):
 95         self.startDraw(e)
 96         self.drawPad.create_rectangle(e.x-5,e.y-5,e.x+5,e.y+5,fill='black')
 97         self.x=e.x
 98         self.y=e.y
 99 
100     def stopDraw(self,e):
101         self.startDrawFlag=False
102         self.lastDraw=0 # 画下一条线时保留之前画的线不被删除
103 
104     def changeColor(self,e):
105         if e.char=='r': # 区别大小写
106             self.fgcolor='#ff0000'
107         elif e.char=='g':
108             self.fgcolor='green'
109         elif e.char=='b':
110             self.fgcolor='blue'
111 
112 def main():
113     root=Tk();root.geometry('900x500+200+140')
114     App(root)
115     root.mainloop()
116 
117 if __name__ == '__main__':
118     main()

 

 

未完

待续

posted @ 2019-12-13 23:23  xiongjiawei  阅读(243)  评论(0)    收藏  举报