Tkinter
主窗口和位置大小
通过geometry('wxh±x±y')
进行设置,w为宽度,h为高度,+x表示距离屏幕左边的距离,-x表示距离屏幕右边的距离,+y表示距离屏幕上边的距离,-y表示屏幕下边的距离
# -*- coding: UTF-8 -*- @Date :2022/9/16 9:18from tkinter import *
from tkinter import messageboxwindow = Tk()#创建一个顶层窗口对象;
window.title('第一个GUI程序') # 窗口的标题
window.geometry('500x300+100+200') # 宽度500像素,高度300像素,距离左边100像素,距离上边200像素
bunt1 = Button(window)
bunt1['text'] = 'click me 'bunt1.pack()def flower(e):messagebox.showinfo("Message", "送你一朵玫瑰花")bunt1.bind("<Button-1>", flower)
window.mainloop()#事件循环。
GUI编程描述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IkN3aJdc-1664425162728)(E:\MarkDown\markdown\imgs\54d8a6eb7eced27d4871d352d1edd346.png)]
Tkinter和Wm
Tkinter的GUI组件有两个根父类,他们都直接继承了object类:
- Misc:是所有组件的根父类
- Wm:主要提供了一些与窗口管理器通信的功能函数
Tk
Misc和Wm派生出子类Tk,它代表应用程序的主窗口,一般用户程序都需要直接或间接使用Tk
Pack、Place、Grid
Pack、Place、Grid是布局管理器,布局管理器组件的,大小,位置,通过布局管理器可以将容器中的组件实现合理的排布
BaseWidget
BaseWidget是所有组件的父类
Widget
Widget是所有组件类的父类,Widget一共有四个父类:Base Widget、Pack、Grid、Place,意味着所有GUI组件同时具备者四个父类的属性和方法
常用组件汇总
Tkinter | 名称 | 简介 |
---|---|---|
Toplevel | 顶层 | 容器类,可用于为其他组件提供单独的容器,Toplevel有点类似于窗口 |
Button | 按钮 | 代表按钮组件 |
Canvas | 画布 | 提供绘图功能,包括直线,矩形,椭圆,多边形,位图 |
Checkbutton | 复选框 | 可供用户勾选的复选框 |
Entry | 单行输入框 | 用户可输入内容 |
Label | 标签 | 用于显示不可编辑的文本或图标 |
LabelFrame | 容器 | 也是容器组件,类似于Frame,但它支持添加标题 |
Menu | 菜单 | 菜单组件 |
Menubutton | 菜单按钮 | 用来包含菜单的按钮(包括下拉式,层叠式) |
OptionMenu | 菜单按钮 | Menubotton的子类,也代表菜单按钮,可以通过按钮打开一个菜单 |
Message | 消息框 | 类似于标签,但可以显示多行文本,后来当Label也能显示 |
Listbox | 列表框 | 列出多个选项,供用户先择 |
Frame | 容器 | 用于装载其他GUI组件 |
GUI应用程序类的经典写法
通过类Application组织整个GUI程序,类Application继承了Frame及通过继承拥有了父类的特性,通过构造函数__init__()
初始化窗口中的对象,通过createWidgests()
方法创建窗口中的对象。
Frame框架是tkinter
组件,标识一个矩形的区域,Frame一般作为容器使用,可以放置其他组件,从而实现复杂的布局
# -*- coding: UTF-8 -*- @Date :2022/9/16 10:15from tkinter import *
from tkinter import messageboxclass Application(Frame):"""一个经典的GUI程序类的写法"""def __init__(self, master=None):super().__init__(master) # super代表是父类的定义,而不是父类对象self.master = masterself.pack()self.createWidget()def createWidget(self):"""创建组件"""self.btn01 = Button(self)self.btn01['text'] = '点击送花'self.btn01.pack()self.btn01['command'] = self.flower# 创建退出按钮self.btnQuit = Button(self, text='退出', command=root.destroy)self.btnQuit.pack()def flower(self):messagebox.showinfo('送花', '送你一朵玫瑰花')if __name__ == '__main__':root = Tk()root.geometry('400x200+200+300')root.title("一个经典的GUI程序类的测试")app = Application(master=root)root.mainloop()
简单组件
Label标签
label主要用来显示文本信息,也可显示图像
常用属性:
-
width、height:
用于显示区域大小,如果显示文本,则以单个英文字符大小为单位(一个汉字占两个字符)如果显示图像,则以像素为单位,默认值是根据具体显示的内容动态调整
-
font
指定字体和字体大小 font=(font_name,size)
-
image:
显示在Label上的图像,目前tkinter只支持gif格式
-
fg和bg
fg(foreground):前景色\ bg(background)背景色
-
justify
针对多行文字的对齐,可设置justify属性,可选值:left,right,center
# -*- coding: UTF-8 -*- @Date :2022/9/16 10:47
from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.pack()self.createWidget()def createWidget(self):"""创建组件"""self.label01 = Label(self,text='我学Python',width=10,height=2,bg='black',fg='yellow')self.label01.pack()self.label02 = Label(text='人生苦短',width=10,height=2,bg='blue',fg='red',font=('楷体', 20))self.label02.pack()# 显示图像global photo # photo声明成全局变量,如果是局部,本方法执行完毕后,图片对象销毁,窗口显示不出来图像photo = PhotoImage(file='img/img.png')self.label03 = Label(image=photo)self.label03.pack()#显示多行文本self.label04=Label(text='人生苦短,我学Python',borderwidth=2,relief='solid',justify='right')self.label04.pack()if __name__ == '__main__':root = Tk()root.title('Label标签测试')root.geometry('500x300+200+200')app = Application(master=root)root.mainloop()
效果展示
Option选项
- 创建对象时,使用命名参数(也叫关键字参数)
window=Button(self,fg='red',bg='blue')
- 创建对象后,使用字典索引方式
window['fg']='red'
window['bg']='blue'
- 创建对象后,使用config()方法
window.config(fg='red',bg='blue')
Button
Button用来执行用户点击操作,Button可以包含文本,也可包含图像,按钮被单机后会自动调用对应事件绑定方法
# -*- coding: UTF-8 -*- @Date :2022/9/16 11:36
from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.createWidget()def createWidget(self):"""创建组件"""self.butn01 = Button(root, text='登录', command=self.login)self.butn01.pack()global photophoto = PhotoImage(file='img/start.png')self.butn02 = Button(root, image=photo, command=self.login)self.butn02.pack()# self.butn02.config(state='disabled') # 设置按钮为禁用# 点击图片退出global photo2photo2=PhotoImage(file='img/end.png')self.butnQuit = Button(root,image=photo2, command=root.destroy)self.butnQuit.pack()def login(self):messagebox.showinfo('自学网', '登录成功,开始学习吧!')if __name__ == '__main__':root = Tk()root.title("Button按钮")root.geometry('600x400+100+200')app = Application(master=root)root.mainloop()
Entry 当行文本框
Entry用来接收一行字符串的控件,如果用户输入的文字长度长于Entry控件的宽度,文字会自动向后滚动,入宫输入多行文本,需要使用Text控件
# -*- coding: UTF-8 -*- @Date :2022/9/16 13:34from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.pack()self.createWidget()def createWidget(self):"""创建登录界面的组件"""self.label01 = Label(text='用户名')self.label01.pack()# StringVar变量绑定到指定的组件# StringVar变量的值发生变换,组件内容也发生变化# 组件的内容发生变化,StringVar变量的值也发生变化v1 = StringVar()self.entry01 = Entry(textvariable=v1)self.entry01.pack()v1.set('admin')# print(v1.get());print(self.entry01.get())# 创建密码框self.label02 = Label(text='密码')self.label02.pack()v2 = StringVar()self.entry02 = Entry(textvariable=v2, show='*')self.entry02.pack()Button(self, text='登录', command=self.login).pack()def login(self):username = self.entry01.get()password = self.entry02.get()print('用户名' + username)print('密码' + password)"""模拟数据库比对数据"""if username == 'zhao' and password == '123456':messagebox.showinfo("自学网欢迎您", '开始自学吧')else:messagebox.showinfo("自学网欢迎您", '登陆失败!用户名或密码错误')if __name__ == '__main__':root = Tk()root.title('Entry单行文本')root.geometry('500x300+100+200')app = Application(master=root)root.mainloop()
Text多行文本框
Text的主要用户显示多行文本,还可以显示网页链接,图片,HTML页面,甚至CSS样式表,添加组件等,因此,也常被当做简单的文本处理器、文本编辑器或者网页浏览器来使用,比如:IDEL就是Text组件构成的
# -*- coding: UTF-8 -*- @Date :2022/9/16 14:02from tkinter import *
from tkinter import messagebox
import webbrowserclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.pack()self.createWidget()def createWidget(self):""""""self.w1 = Text(width=40, height=12, bg='gray')self.w1.pack()self.w1.insert(1.0, '一二三四五,\n上山岛老鼠')self.w1.insert(2.3, '人生苦短,我学Python')Button(text='重复插入文本', command=self.insertText).pack(side='left')Button(text='返回文本', command=self.returnText).pack(side='left')Button(text='添加图片', command=self.addImage).pack(side='left')Button(text='添加组件', command=self.addWidget).pack(side='left')Button(text='通过tag精确控制文本', command=self.testTag).pack(side='left')Button(text='退出', command=window.destroy).pack(side='left')def insertText(self):# INSERT索引表示在光标处插入self.w1.insert(INSERT, 'zhao')self.w1.insert(1.8, '糖衣炮弹')# END索引号表示在最后插入self.w1.insert(END, '[xxxx.com]')def returnText(self):# Indexes(索引)是用来指向Text组件中文本的位置,Text的组件索引也是对应事件字符之间的位置# 核心:行号以1开始,列号以0开始print(self.w1.get(1.2, 1.6))print('所有文本内容\n' + self.w1.get(1.0, END))def addImage(self):self.photo = PhotoImage(file='img/dog.png')self.w1.image_create(END, image=self.photo)def addWidget(self):b1=Button(self.w1,text='Python')#在text创建组件的命令self.w1.window_create(INSERT,window=b1)def testTag(self):self.w1.delete(1.0,END)self.w1.insert(INSERT,'girl girl girl girl girl day boy\n insert common\n shabi dsakfh fsdlkhaf\n hakfha\n''百度')self.w1.tag_add('girl',1.0,1.9)self.w1.tag_config('good',background='yellow',foreground='red')self.w1.tag_add('baidu',5.0,5.2)self.w1.tag_config('baidu',underline=True)self.w1.tag_bind('baidu','<Button-1>',self.webshow)def webshow(self,event):webbrowser.open('http://www.baidu.com')if __name__ == '__main__':window = Tk()window.title('多行文本')window.geometry('500x400+100+200')app = Application(master=window)window.mainloop()
Radiobutton单选按钮
Radiobutton控件用于选择通过一组单选按钮中的一个
Radiobutton可以显示文本,也可以显示图像
# -*- coding: UTF-8 -*- @Date :2022/9/16 14:46from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.createWidget()def createWidget(self):self.v = StringVar()self.v.set('F') # 默认设置为女性self.r1 = Radiobutton(text='男性', value='M', variable=self.v)self.r2 = Radiobutton(text='女性', value='F', variable=self.v)self.r1.pack(side='left')self.r2.pack(side='left')Button(text='确定', command=self.confirm).pack(side='left')def confirm(self):messagebox.showinfo('测试', '选择的性别为' + self.v.get())if __name__ == '__main__':root = Tk()root.geometry('200x100+100+100')app = Application(master=root)root.mainloop()
Checkbutton 复选按钮
Checkbutton控件用于选择多个按钮的情况,
Checkbutton可以显示文本也可以显示图像
# -*- coding: UTF-8 -*- @Date :2022/9/16 14:46from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.createWidget()def createWidget(self):self.codeHobby = IntVar()self.videoHobby = IntVar()self.c1 = Checkbutton(text='敲代码', onvalue=1, offvalue=0,variable=self.codeHobby) # onvalue,offvalue当选中的时候返回是1,不选是0self.c2 = Checkbutton(text='看小视频', onvalue=1, offvalue=0, variable=self.videoHobby)self.c1.pack(side='left')self.c2.pack(side='left')Button(text='确定', command=self.confirm).pack(side='left')def confirm(self):if self.videoHobby.get() == 1:messagebox.showinfo('测试', '我爱看电影,你呢')if self.videoHobby.get() == 1:messagebox.showinfo('测试', '人生苦短,我学Python')if __name__ == '__main__':root = Tk()root.geometry('300x100+100+100')app = Application(master=root)root.mainloop()
canvas画布
是一个矩形区域,可以防止任何图形,图像,组件等
# -*- coding: UTF-8 -*- @Date :2022/9/16 15:08
import random
from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.pack()self.createWidget()def createWidget(self):# 画一条直线self.canvas = Canvas(self, width=300, height=200, bg='green')self.canvas.pack()# 画一个矩形line = self.canvas.create_line(10, 10, 30, 20, 40, 50)# 画一个矩形rect = self.canvas.create_rectangle((50, 50, 100, 100))#画一个椭圆,坐标两双,为椭圆的边界矩形左上角和底部右下角oval=self.canvas.create_oval(50,50,100,100)global photophoto=PhotoImage(file='img/img.png')self.canvas.create_image(150,170,image=photo)Button(self,text='画十个矩形',command=self.draw).pack(side='left')def draw(self):for i in range(0,10):num1=int(self.canvas['width'])/2num2=int(self.canvas['height'])/2x1=random.randrange(num1)y1=random.randrange(num2)x2=x1+random.randrange(num1)y2=y1+random.randrange(num2)self.canvas.create_rectangle(x1,y1,x2,y2)if __name__ == '__main__':root = Tk()root.geometry('500x300+200+300')app = Application(root)root.mainloop()
布局管理器
grid布局管理器
grid表格布局,采用表格结构组织组件,子组件的位置由行和列的单元格来确定, 并且可以跨行和跨列,从而实现复杂的布局
# -*- coding: UTF-8 -*- @Date :2022/9/16 15:44
# -*- coding: UTF-8 -*- @Date :2022/9/16 15:08
import random
from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.pack()self.createWidget()def createWidget(self):self.label01 = Label(self, text='用户名')self.label01.grid(row=0, column=0)self.entry01 = Entry(self)self.entry01.grid(row=0, column=1)Label(self, text='用户名为手机号').grid(row=0, column=2)Label(self, text='密码').grid(row=1, column=0)Entry(self, show='*').grid(row=1, column=1)Button(self, text='登录').grid(row=2, column=1, sticky=EW)Button(self, text='取消').grid(row=2, column=2, sticky=E)if __name__ == '__main__':root = Tk()root.geometry('500x300+200+300')app = Application(root)root.mainloop()
Grid实现计算器页面
# -*- coding: UTF-8 -*- @Date :2022/9/16 16:02
from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.pack()self.createWidget()def createWidget(self):"""通过Grid 实现计算器界面"""btnTex = (('MC', 'M+', 'M-', 'MR'),('C', '±', '/', 'x'),('7', '8', '9', '-'),('4', '5', '6', '+'),('1', '2', '3', '='),('0', '.'))Entry(self).grid(row=0, column=0, columnspan=4, pady=10) # 跨4列for rindex, r in enumerate(btnTex):for cindex, c in enumerate(r):if c =='=':Button(self,text=c,width=2).grid(row=rindex+1,column=cindex,rowspan=2,sticky=NSEW)elif c=='0':Button(self,text=c,width=2).grid(row=rindex+1,column=cindex,columnspan=2,sticky=NSEW)elif c=='.':Button(self,text=c,width=2).grid(row=rindex+1,column=cindex+1,sticky=NSEW)else:Button(self, text=c, width=2).grid(row=rindex + 1, column=cindex,sticky=EW)if __name__ == '__main__':root = Tk()root.geometry('250x250+200+300')app = Application(master=root)root.mainloop()
pack布局管理器
pack按照组件的创建顺序将子组件添加到父组件,按照垂直或者水平的方向自然排布,如果不指定任何选项,默认在父组件中自顶向下垂直添加组件
pack是代码量最少,最简单的一种,可以用于快速生成界面
# -*- coding: UTF-8 -*- @Date :2022/9/16 17:00from tkinter import *
root=Tk()
root.geometry("700x220")
#Frame是一个矩形区域,就是用来防止其他子组件
f1=Frame(root)
f1.pack()
f2=Frame(root)
f2.pack()btnText=('流行风','中国风','日本风','重金属','轻音乐')
for txt in btnText:Button(f1,text=txt).pack(side='left',padx='10')
for i in range(1,20):Label(f2,width=5,height=10,borderwidth=1,relief='solid',bg='black' if i%2==0 else 'white').pack(side='left',padx=2)root.mainloop()
place布局管理器
可以通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景
# -*- coding: UTF-8 -*- @Date :2022/9/16 17:29
from tkinter import *root = Tk()
root.geometry("500x300")
root.title('布局管理器Place'
)
root['bg'] = 'white'
f1 = Frame(root, width=200, height=200, bg='green')
f1.place(x=30, y=30)Button(root, text='Python').place(relx=0.2, x=100, y=20, relwidth=0.2, relheight=0.5)
Button(f1, text='面向对象').place(relx=0.6, rely=0.7)
Button(f1, text='zhao').place(relx=0.5, rely=0.2)
root.mainloop()
通过palce布局管理器对扑克牌进行位置控制
# -*- coding: UTF-8 -*- @Date :2022/9/16 17:37
from tkinter import *
from tkinter import messageboxclass Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.pack()self.createWidget()def createWidget(self):"""通过place布局管理器实现扑克牌位置控制"""self.photo = PhotoImage(file='img/puke/puke1.png')self.puke1 = Label(root, image=self.photo)self.puke1.place(x=10, y=50)self.photos = [PhotoImage(file='img/puke/puke' + str(i + 1) + '.png') for i in range(3)]self.pukes = [Label(self.master, image=self.photos[i]) for i in range(3)]for i in range(3):self.pukes[i].place(x=10 + i * 60, y=50)# 对所有的Label增加事件处理self.pukes[0].bind_class("Label", "<Button-1>", self.chupai)def chupai(self, event):# print(event.widget.winfo_geometry())# print(event.widget.winfo_x()) # 获取主键的x坐标# print(event.widget.winfo_y()) # 获得y坐标if event.widget.winfo_y() == 50:event.widget.place(y=30)else:event.widget.place(y=60)if __name__ == '__main__':root = Tk()root.geometry("700x600+200+300")app = Application(root)root.mainloop()
事件处理
一个GUI应用整个生命周期都处在一个消息循环(eventloop)中,它等待事件的发生,并作出相应的处理
Tkinter提供了用以处理相关事件的机制,处理函数可以被绑定给各个控件的各种事件
widget.bind(event,handler)
如果相关事件发生,hadler函数会被触发,事件对象event会传递给handler函数
鼠标和键盘事件
event对象常用属性
# -*- coding: UTF-8 -*- @Date :2022/9/16 20:00from tkinter import *root = Tk()
root.geometry("530x300")
c1 = Canvas(root, width=200, height=200, bg='green')
c1.pack()def mouseTest(event):print('鼠标左键单机位置(相对于父容器):{0},{1}'.format(event.x, event.y))print('鼠标左键单机位置(相对于屏幕):{0}{1}'.format(event.x_root, event.y_root))print('事件绑定的组件:{0}'.format(event.widget))def testDrag(event):c1.create_oval(event.x, event.y, event.x + 1, event.y + 1)def keyboardTest(event):print('键的keycode:{0},键的char:{1},键的keysym:{2}'.format(event.keycode, event.char, event.keysym))def press_a_test(event):print('press_a')def release_a_test(event):print('release_a')c1.bind('<Button-1>', mouseTest)
c1.bind('<B1-Motion>', testDrag)root.bind('<KeyPress>', keyboardTest)
root.bind("<KeyPress-a>", press_a_test)
root.bind("<KeyRelease-a>", release_a_test)
root.mainloop()
多种事件绑定方式
-
组件对象的绑定
-
通过command属性绑定,(适合简单不需要获取event对象)
-
Button(root,text='登录',command=login0)
-
通过bind()方法绑定(适合需要获取event 对象
-
c1=Canvas();c1.bind("<Button-1>",drawLine)
-
-
组件类的绑定
-
调用对象的bind_class函数,将改组件类所有的组件绑定事件:
-
w.bind_class("Widget","event",eventhanler)
-
# -*- coding: UTF-8 -*- @Date :2022/9/16 20:32from tkinter import *
from tkinter import messageboxroot = Tk()
root.geometry("300x30")def mouseTest1(event):print('bind()方式绑定,可以获取event对象')print(event.widget)def mouseTest2(a, b):print('a={0},b={1}'.format(a, b))print('command方式绑定,不能直接获取event对象')def mouseTest3(event):print('右键单机事件,绑定给所有按钮了')print(event.widget)b1 = Button(root, text='测试bind()绑定')
b1.pack(side='left')
# bind直接绑定事件
b1.bind("<Button-1>", mouseTest1)# command属性直接绑定事件
b2 = Button(root, text='测试command2', command=lambda: mouseTest2("zhao", "lisi"))
b2.pack(side='left')# 给所有Button按钮都绑定右键单机事件<Button-2>
b1.bind_class('Button', "<Button-2>", mouseTest3)root.mainloop()
其他组件
OptionMenu选择项
用来多选一,选中的项在顶部显示。
# -*- coding: UTF-8 -*- @Date :2022/9/16 20:50from tkinter import *root = Tk()
root.geometry("200x100")
v = StringVar()
v.set('黑马程序员')
om = OptionMenu(root, v, '千锋教育', '字节跳动', '华为')
om['width'] = 10
om.pack()def test1():print('最想选择哪一个:', v.get())Button(root, text='确定', command=test1).pack()
root.mainloop()
Scale移动滑块
用于在指定的数值区间,通过滑块的移动来选择值
# -*- coding: UTF-8 -*- @Date :2022/9/16 20:58from tkinter import *root = Tk()
root.geometry("400x150")def test1(value):print('滑块的值:',value)newFont = ("宋体", value)a.config(font=newFont)s1 = Scale(root, from_=10, to=50, length=200, tickinterval=5, orient=HORIZONTAL, command=test1)
s1.pack()a=Label(root,text='Python',width=10,height=1,bg='black',fg='white')
a.pack()
root.mainloop()
颜色选择框
颜色选择框帮助我们设置前景色,背景色,画笔颜色,字体颜色等
# -*- coding: UTF-8 -*- @Date :2022/9/16 21:06from tkinter import *
from tkinter.colorchooser import *root=Tk();root.geometry("400x150")
def text():s1=askcolor(color='red',title='选择背景色')print(s1)#s1的值是:((0.0,0.0,255,99609375),"#0000ff")root.config(bg=s1[1])Button(root,text='选择背景色',command=text).pack()root.mainloop()
文件选择框
文件对话框帮助我们实现可视化的操作目录、操作文件。最后,将文件、目录的信息传入到程序中。文件
# -*- coding: UTF-8 -*- @Date :2022/9/16 21:11from tkinter import *
from tkinter.filedialog import *root=Tk()
root.geometry("400x100")
def test():f=askopenfile(title='上传文件',initialdir='f:',filetypes=[("视频文件",'.mp4')])show['text']=f
Button(root,text='选择编辑的视频文件',command=test).pack()
show=Label(root,width=40,height=3,bg='green')
show.pack()
root.mainloop()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IUwFcV1l-1664425162731)(E:\MarkDown\markdown\imgs\210350f74045499599d613dc26bc36d2.png)]
命名参数option的常见值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RSYma3Qb-1664425162733)(E:\MarkDown\markdown\imgs\c04e89321fd342b7a80d429a32e61813.png)]
简单对话框
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oPZuzB2a-1664425162734)(E:\MarkDown\markdown\imgs\eef5bbed724e4996b5f3c5286ed54404.png)]
# -*- coding: UTF-8 -*- @Date :2022/9/17 8:26from tkinter import *
from tkinter.simpledialog import *root = Tk()
root.geometry("400x100")def test():a = askinteger(title='输入年龄', prompt='请输入年龄', initialvalue=18, minvalue=1, maxvalue=150)show['text'] = aButton(root, text='多大了你?', command=test).pack()
show = Label(root, width=40, height=3, bg='green')
show.pack()root.mainloop()
上下文菜单
# -*- coding: UTF-8 -*- @Date :2022/9/17 8:32from tkinter import *
from tkinter.filedialog import *class Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.textpad = Noneself.pack()self.createWidget()def createWidget(self):"""创建主菜单栏"""menubar = Menu(root)# 创建子菜单menuFile = Menu(menubar)menuEdit = Menu(menubar)menuHelp = Menu(menubar)# 将子菜单加入到主菜单栏menubar.add_cascade(label='文件(F)', menu=menuFile)menubar.add_cascade(label='编辑(E)', menu=menuEdit)menubar.add_cascade(label='帮助(H)', menu=menuHelp)# 添加菜单项menuFile.add_command(label='新建', accelerator="ctrl+n", command=self.test)menuFile.add_command(label='打开', accelerator="ctrl+o", command=self.test)menuFile.add_command(label='保存', accelerator="ctrl+s", command=self.test)menuFile.add_separator() # 添加分割线menuFile.add_command(label='退出', accelerator='ctrl+q', command=self.test)# 将主菜单加到根窗口root['menu'] = menubar# 文本编辑区self.textpad = Text(root, width=50, height=30)self.textpad.pack()# 创建上下菜单self.contextMenu = Menu(root)self.contextMenu.add_command(label='背景颜色', command=self.test)# 为右键绑定事件root.bind("<Button-3>", self.createContextMenu)def test(self):passdef createContextMenu(self, event):# 菜单在鼠标右键单机的座标处显示self.contextMenu.post(event.x_root, event.y_root)if __name__ == '__main__':root = Tk()root.geometry("400x200")root.title("简易记事本")app = Application(master=root)root.mainloop()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jf211Z1t-1664425162735)(E:\MarkDown\markdown\imgs\1ebad2056f624da2b5c13b1f0320307c.png)]
记事本优化
# -*- coding: UTF-8 -*- @Date :2022/9/17 8:32from tkinter import *
from tkinter.colorchooser import askcolor
from tkinter.filedialog import *class Application(Frame):def __init__(self, master=None):super().__init__(master)self.filename = Noneself.master = masterself.textpad = Noneself.pack()self.createWidget()def createWidget(self):"""创建主菜单栏"""menubar = Menu(root)# 创建子菜单menuFile = Menu(menubar)menuEdit = Menu(menubar)menuHelp = Menu(menubar)# 将子菜单加入到主菜单栏menubar.add_cascade(label='文件(F)', menu=menuFile)menubar.add_cascade(label='编辑(E)', menu=menuEdit)menubar.add_cascade(label='帮助(H)', menu=menuHelp)# 添加菜单项menuFile.add_command(label='新建', accelerator="ctrl+n", command=self.newfile)menuFile.add_command(label='打开', accelerator="ctrl+o", command=self.openfile)menuFile.add_command(label='保存', accelerator="ctrl+s", command=self.savefile)menuFile.add_separator() # 添加分割线menuFile.add_command(label='退出', accelerator='ctrl+q', command=self.exit)# 将主菜单加到根窗口root['menu'] = menubar# 增加快捷键的处理root.bind('<Control-n>', lambda event: self.newfile())root.bind('<Control-s>', lambda event: self.savefile())root.bind('<Control-q>', lambda event: self.exit())root.bind('<Control-o>', lambda event: self.openfile())# 文本编辑区self.textpad = Text(root, width=50, height=30)self.textpad.pack()# 创建上下菜单self.contextMenu = Menu(root)self.contextMenu.add_command(label='背景颜色', command=self.openAskColor)# 为右键绑定事件root.bind("<Button-3>", self.createContextMenu)def newfile(self):self.filename = asksaveasfilename(title='另存为', initialfile='未命名.txt',filetypes=[("文本 文档", '.txt')],defaultextension='.txt')self.savefile()def openfile(self):self.textpad.delete("1.0", "end")with askopenfile(title='打开文本文件') as f:self.textpad.insert(INSERT, f.read())self.filename = f.namedef savefile(self):with open(self.filename, 'w', encoding='utf-8') as f:c = self.textpad.get(1.0, END)f.write(c)def exit(self):root.quit()def openAskColor(self):s1 = askcolor(color='red', title='选择背景色')self.textpad.config(bg=s1[1])def createContextMenu(self, event):# 菜单在鼠标右键单机的座标处显示self.contextMenu.post(event.x_root, event.y_root)if __name__ == '__main__':root = Tk()root.geometry("400x200")root.title("简易记事本")app = Application(master=root)root.mainloop()
画图软件开发
"""
包含功能如下:
1.画笔
2.矩形/椭圆绘制
3.清屏
4.橡皮擦
5.直线/带箭头的执行
6.修改画笔的颜色、背景颜色
"""
# -*- coding: UTF-8 -*- @Date :2022/9/17 8:32from tkinter import *from tkinter import messagebox# 窗口的宽度和高度
from tkinter.colorchooser import askcolorwin_width = 900
win_height = 450class Application(Frame):def __init__(self, master=None):super().__init__(master)self.master = masterself.bgcolor = '#000'self.x = 0self.y = 0self.lastDraw = 0 # 表示最后绘制的图形的idself.fgcolor = 'red'self.startDraw = Falseself.pack()self.createWidget()def createWidget(self):"""创建绘图区"""self.drawpad = Canvas(root, width=win_width, height=win_height * 0.9, bg=self.bgcolor)self.drawpad.pack()# 创建按钮btn_start = Button(root, text='开始', name='start')btn_start.pack(side='left', padx='10')btn_pen = Button(root, text='画笔', name='pen')btn_pen.pack(side='left', padx='10')btn_rect = Button(root, text='矩形', name='rect')btn_rect.pack(side='left', padx='10')btn_clear = Button(root, text='清屏', name='clear')btn_clear.pack(side='left', padx='10')btn_eraor = Button(root, text='橡皮擦', name='erasor')btn_eraor.pack(side='left', padx='10')btn_line = Button(root, text='直线', name='line')btn_line.pack(side='left', padx='10')btn_lineArrow = Button(root, text='箭头直线', name='lineArrow')btn_lineArrow.pack(side='left', padx='10')btn_color = Button(root, text='箭头直线', name='color')btn_color.pack(side='left', padx='10')# 事件处理btn_pen.bind_class("Button", "<1>", self.eventManger)self.drawpad.bind("<ButtonRelease-1>", self.stopDraw)#增加颜色切换的快捷键root.bind('<KeyPress-r>',self.kuaijiejian)root.bind('<KeyPress-g>',self.kuaijiejian)root.bind('<KeyPress-y>',self.kuaijiejian)def eventManger(self, event):name = event.widget.winfo_name()print(name)if name == 'line':self.drawpad.bind("<B1-Motion>", self.myline)elif name == 'lineArrow':self.drawpad.bind("<B1-Motion>", self.lineArrow)elif name == 'rect':self.drawpad.bind("<B1-Motion>", self.myRect)elif name == 'pen':self.drawpad.bind("<B1-Motion>", self.mypen)elif name == 'erasor':self.drawpad.bind("<B1-Motion>", self.Erasor)elif name == 'clear':self.drawpad.delete("all")elif name == 'color':c = askcolor(color=self.fgcolor, title='选择画笔颜色')self.fgcolor = c[1]def stopDraw(self, event):self.startDraw = Falseself.lastDraw = 0def Draw(self, event):self.drawpad.delete(self.lastDraw)if not self.startDraw:self.startDraw = Trueself.x = event.xself.y = event.ydef myline(self, event):self.Draw(event)self.lastDraw = self.drawpad.create_line(self.x, self.y, event.x, event.y, fill=self.fgcolor)def lineArrow(self, event):self.Draw(event)self.lastDraw = self.drawpad.create_line(self.x, self.y, event.x, event.y, arrow=LAST, fill=self.fgcolor)def myRect(self, event):self.Draw(event)self.lastDraw = self.drawpad.create_rectangle(self.x, self.y, event.x, event.y, outline=self.fgcolor)def mypen(self, event):self.Draw(event)self.drawpad.create_line(self.x, self.y, event.x, event.y, fill=self.fgcolor)self.x = event.xself.y = event.ydef Erasor(self, event):self.Draw(event)self.drawpad.create_rectangle(event.x - 4, event.y - 4, event.x + 4, event.y + 4, fill=self.bgcolor)self.x = event.xself.y = event.ydef kuaijiejian(self,event):if event.char =='r':self.fgcolor='#ff0000'elif event.char=='g':self.fgcolor='#00ff00'elif event.char=='y':self.fgcolor='#ffff00'if __name__ == '__main__':root = Tk()root.geometry(str(win_width) + 'x' + str(win_height) + "+200+300")root.title("程序员的画图软件开发")app = Application(master=root)root.mainloop()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AocuetDL-1664425162737)(E:\MarkDown\markdown\imgs\0432bb77f8234676b80b95c733cb9bf7.png)]