Bootstrap

python tkinter从入门到撩妹-整蛊弹窗-1

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()
;