python版本:3.6
图片素材前往我的github下载:https://github.com/BigShuang/liaomei
效果如图
动画见本人b站投稿
目录
1实现一个无法关闭的窗体
使用tkinter实现基础窗体只需如下三行代码
import tkinter as tk
win = tk.Tk()
win.mainloop()
运行结果如下图
这是个没有任何内容的窗体,点击右上角的×会关闭这个窗体。
要实现整蛊,就必须让窗体无法通过这个×关闭
这里我们仔细看前面三行代码,会发现窗体是使用tkinter
里面的TK
类
点击右上角的×实际上调用的是TK
类的destory
方法,该方法源码如下
这里我们新建一个TK
类的子类并重写destory
方法使其失效就可以。
代码如下
import tkinter as tk
# 新建无法直接关闭的TK类
class NewTk(tk.Tk):
def destroy(self):
# 点击界面右上角的关闭按钮时,会调用本函数,
# 覆盖掉了父类的关闭方法,使得界面无法关闭
pass
win = NewTk()
win.mainloop()
此时运行出来的窗体就不可以通过右上角的×关闭了。
补充:如果你使用的不是pycharm编辑器而是sublimetext这种,那么可能你运行后会发现这个窗口你关不了,因为你无法停止运行这个py脚本,这个时候只能用任务管理器关闭该窗口了,关闭任务管理器中的如下图标的任务就好
2 添加一行字一张图片和两个按钮
在窗体里添加图片只需要原有代码的win = NewTk()
和win.mainloop()
之间添加
如下代码
# 这里的图片路径对于小白来说,最保险是绝对路径
# 如果你的图片001.gif和代码在一个文件夹,直接可以使用下面一行
# IMGPATH = "001.gif"
# 如果代码文件和图片所在文件夹在同一目录,即代码和img文件夹在同一目录,直接用下一行
# IMGPATH = "img/001.gif"
# 我的github里,代码文件夹和图片文件夹在同一目录,所以使用的是下一行
IMGPATH = "../img/001.gif"
photo = tk.PhotoImage(file=IMGPATH)
imgLabel = tk.Label(win,image=photo)
imgLabel.place(x=0, y=0)
此时运行会发现窗体太小,只展示了图片左上角的部分区域
如图
所以需要调整窗体大小,调整后设置图片位置到中间区域
调整后代码如下
import tkinter as tk
# 新建无法直接关闭的TK类
class NewTk(tk.Tk):
def destroy(self):
# 点击界面右上角的关闭按钮时,会调用本函数,
# 覆盖掉了父类的关闭方法,使得界面无法关闭
pass
win = NewTk()
WINWIDTH = 800
WINHEIGHT = 600
win.geometry("%sx%s" % (WINWIDTH, WINHEIGHT))
IMGPATH = "../img/001.gif"
photo = tk.PhotoImage(file=IMGPATH)
imgLabel = tk.Label(win, image=photo)
imgLabel.place(x=180, y=80)
win.mainloop()
再在图片上添加一行文字用于提问,代码如下(代码放在imgLabel.place(x=180, y=80)
和win.mainloop()
这两行之间)
question = "我喜欢你,有机会吗?"
q = tk.Label(win, text=question)
q.place(x=180, y=20)
然后再在win.mainloop()
上面添加按钮,代码如下
yes = "有"
no = "没有"
yes_button = tk.Button(win, text=yes)
yes_button.place(x=100, y=500)
no_button=tk.Button(win, text=no)
no_button.place(x=400, y=500)
此时页面运行效果如下
整体样子有些丑陋,一个是布局丑,一个是各个控件大小不协调导致的丑
我们需要修改下
3 样式优化
首先,调整下这个按钮和图片的位置关系,并给窗体添加标题,比如叫做大妹子,如下图
先调整位置关系,代码如下
import tkinter as tk
IMGPATH = "../img/001.gif"
WINWIDTH = 800
WINHEIGHT = 600
WINX = 400
WINY = 100
img_x = 180
img_y = 60
question_y = 20
button_width = 100
button_height = 40
yes_button_x = img_x - button_width // 2
no_button_x = WINWIDTH - img_x - button_width//2
button_y = 520
question = "我喜欢你,有机会吗?"
yes = "有"
no = "没有"
title = "大妹子"
# 新建无法直接关闭的TK类
class NewTk(tk.Tk):
def destroy(self):
# 点击界面右上角的关闭按钮时,会调用本函数,
# 覆盖掉了父类的关闭方法,使得界面无法关闭
pass
win = NewTk()
win.title(title)
win.geometry("%sx%s+%s+%s" % (WINWIDTH, WINHEIGHT, WINX, WINY))
photo = tk.PhotoImage(file=IMGPATH)
imgLabel = tk.Label(win, image=photo)
imgLabel.place(x=img_x, y=img_y)
q = tk.Label(win, text=question)
q.place(x=img_x, y=question_y)
yes_button = tk.Button(win, text=yes)
yes_button.place(x=yes_button_x, y=button_y, width=button_width, height=button_height)
no_button=tk.Button(win, text=no)
no_button.place(x=no_button_x, y=button_y, width=button_width, height=button_height)
win.mainloop()
再修改下字体样式,我们可以把最上面的问题文本放大一些
先在开头导入font
类
import tkinter.font as tkFont # 引入字体模块
然后只需要把q = tk.Label(win, text=question)
这行代码改为如下(当然,你必须要确保你电脑里面有微软雅黑这个字体)
quesft = tkFont.Font(family="微软雅黑",size=16, weight=tkFont.BOLD)
q = tk.Label(win, text=question, font=quesft)
同理你也可以修改按钮里面的字体样式,我这里就不做修改了。
4 给按钮添加功能
给yes按钮添加方法
当按钮有被点击的时候
首先先弹窗回复,停顿一秒后关闭整个程序
那么我们首先在开头导入time
库
import time
再在yes_button = tk.Button(win, text=yes)
这行代码之前添加按钮对应的方法
# 按钮
def clickyes():
yes_reply = "(*/ω\*)"
top_width = 100
top_height = 50
top = tk.Toplevel()
# 设置弹出窗口位置和大小
top_x = WINX+WINWIDTH//2-top_width//2
top_y = WINY+WINHEIGHT//2-top_height//2
top_loc = "{}x{}+{}+{}".format(top_width, top_height, top_x, top_y)
top.geometry(top_loc)
# 添加内容
tk.Label(top, text = yes_reply).pack()
win.update()
time.sleep(1)
# 关闭程序
exit()
然后再给yes按钮绑定这个方法,也就是将yes_button = tk.Button(win, text=yes)
改成如下
yes_button = tk.Button(win, text=yes, command=clickyes)
给no按钮绑定方法
当对方鼠标移到没有这个按钮的时候,我们把这个按钮移开,
让对方无法点击,首先编写对应的方法对绑定上就好
代码如下(添加在win.mainloop()
前面)
def mouse_in_no(event):
bx, by= random.randint(button_width, WINWIDTH-button_width), random.randint(button_height, WINHEIGHT-button_height)
no_button.place(x=bx, y=by)
no_button.bind("<Motion>", mouse_in_no)
此时整个整蛊弹窗就算完成了
完整代码如下
import tkinter as tk
import tkinter.font as tkFont # 引入字体模块
import time
import random
IMGPATH = "../img/001.gif"
WINWIDTH = 800
WINHEIGHT = 600
WINX = 400
WINY = 100
img_x = 180
img_y = 60
question_y = 20
button_width = 100
button_height = 40
yes_button_x = img_x - button_width // 2
no_button_x = WINWIDTH - img_x - button_width//2
button_y = 520
question = "我喜欢你,有机会吗?"
yes = "有"
no = "没有"
title = "大妹子"
# 新建无法直接关闭的TK类
class NewTk(tk.Tk):
def destroy(self):
# 点击界面右上角的关闭按钮时,会调用本函数,
# 覆盖掉了父类的关闭方法,使得界面无法关闭
pass
win = NewTk()
win.title(title)
win.geometry("%sx%s+%s+%s" % (WINWIDTH, WINHEIGHT, WINX, WINY))
photo = tk.PhotoImage(file=IMGPATH)
imgLabel = tk.Label(win, image=photo)
imgLabel.place(x=img_x, y=img_y)
quesft = tkFont.Font(family="微软雅黑", size=16, weight=tkFont.BOLD)
q = tk.Label(win, text=question, font=quesft)
q.place(x=img_x, y=question_y)
# 按钮
def clickyes():
yes_reply = "(*/ω\*)"
top_width = 100
top_height = 50
top = tk.Toplevel()
# 设置弹出窗口位置和大小
top_x = WINX+WINWIDTH//2-top_width//2
top_y = WINY+WINHEIGHT//2-top_height//2
top_loc = "{}x{}+{}+{}".format(top_width, top_height, top_x, top_y)
top.geometry(top_loc)
# 添加内容
tk.Label(top, text = yes_reply).pack()
win.update()
time.sleep(1)
# 关闭程序
exit()
yes_button = tk.Button(win, text=yes, command=clickyes)
yes_button.place(x=yes_button_x, y=button_y, width=button_width, height=button_height)
no_button = tk.Button(win, text=no)
no_button.place(x=no_button_x, y=button_y, width=button_width, height=button_height)
def mouse_in_no(event):
bx, by = random.randint(button_width, WINWIDTH-button_width), random.randint(button_height, WINHEIGHT-button_height)
no_button.place(x=bx, y=by)
no_button.bind("<Motion>", mouse_in_no)
win.mainloop()