python使用tkinter可以在多个操作系统_【Python】使用Tkinter实现多弹窗图形界面程序并转为.exe文件...

最近闲来无事不想学习,就学了一下Python的图形界面编程,顺便做个小玩意逗一下室友,嘿嘿嘿

环境: 系统:Win10 Python:3.6.4 其他工具:PyInstaller

效果v2-b318c36a29c58af54b1f33d8b5eed358.jpg请忽略我娘口三三的壁纸哈哈https://www.zhihu.com/video/1153032043771342848

如果点“不会”的话也会有其他效果哦 ~

Tkinter

这是Python的内置模块,也是这个程序主要用到的包,比较简单容易上手,我大概看了几篇博客就了解了常用的几个功能实现。 主要用到的功能有:各种组件,比如标签(Label,可以是文字图片视频等),按钮(Button),以及新建窗口。 各种组件都有很多可设置的属性,比如内容、长宽、间距、前景背景色等,通过设置属性显示组件。 官方的资料比较少,学习的话可以参考: Python官网 python界面 | Tkinter图形界面开发库 (我看的这个)

开始

导入包:

from tkinter import *

from PIL import Image, ImageTk

首先建立主窗口:

class APP(Frame):

def __init__(self, master=None):

Frame.__init__(self, master)

self.pack(expand=True, fill=BOTH) # 如果用pack()方法排版必须加这一句

w, h = 400, 300

self.master.geometry('%dx%d' % (w, h)) # 设置窗口大小

self.create_widgets()

def create_widgets(self):

load = Image.open('start.jpg').resize((180, 180))

# load = array_to_image('./icon/start.bin')

render = ImageTk.PhotoImage(load)

self.img = Label(self, image=render, width='100', height='100')

self.img.image = render

self.img.pack(expand=YES, fill=BOTH)

self.label = Label(self, text='XXX会有男朋友吗?', font=('微软雅黑', 16))

self.label.pack(pady=20, fill=X, padx=10)

self.yes_button = Button(self, text='不会', width='10', height='1', command=self.yes_command)

self.yes_button.pack(side='left', expand=True, padx=10, pady=10)

self.no_button = Button(self, text='会', width='10', height='1', command=self.no_command)

self.no_button.pack(side='right', expand=True, padx=10, pady=10)Frame类是该窗口所有组件的父容器,可以添加多个组件(Widget)。

每个组件的第一个参数是确定这是哪个窗口下的组件,类里就是self。

图片组件添加时,要先用PIL.Image.open()打开,再用PIL.ImageTk.PhotoImage()转换,具体原- 理我没有查,但是可用。

Button的触发命令用参数command定义,一般是函数,可以自定义,就是当该按钮被点击时触发的事件。

每个组件定义完成后需要使用.pack()函数添加到窗口,按照先后顺序由上到下依次排列。初始化函数也必须要加上self.pack()

pack的参数:方位 side: left,top,right,bottom

拉伸填充 file:X,Y,BOTH,None;水平,竖直,全部,不填充

是否随窗口大小变化 expand:True,False

间距:外部:padx(水平),pady(竖直);内部:ipadx,ipady

pack的逻辑比较简单,也可以使用更复杂的函数,place()和 grid(),前者可以按照坐标安排组件,后者按照网格安排。 具体可参考:Python TKinter 布局管理 (Pack Place Grid)

当点击“会”或“不会”按钮时,触发的函数是self.yes_command和self.no_command,定义如下:

def yes_command(self):

self.yes_button.destroy()

self.no_button.destroy()

load = Image.open('end.jpg').resize((180, 180))

# load = array_to_image('./icon/end.bin')

render = ImageTk.PhotoImage(load)

self.img.destroy()

self.img = Label(self, image=render, width='100', height='100')

self.img.image = render

self.img.pack(expand=YES, fill=BOTH)

self.label.destroy()

self.label = Label(self, text='真乖 ~', font=('微软雅黑', 16))

self.label.pack(pady=30, fill=X, padx=10)

self.after(1500, self.quit)

return

def no_command(self):

no_window = ChildWindow(self)

self.wait_window(no_window) # 此句必须有

self.quit()

return

点击“不会”按钮,当前窗口图片改变,文本改变,延时1.5s后程序退出。 点击“会”按钮,弹出新窗口。

至此,主窗口的程序已经全部完成,主函数:

if __name__ == '__main__':

app = APP()

app.master.title('嘿嘿嘿') # 主窗口的title

app.mainloop()

弹窗

弹窗需要用到模块Toplevel(不知道为啥Frame不能弹窗,有了解的可以留言) 实现和主窗口差不多,不过多介绍了。

class ChildWindow(Toplevel):

images = [[1, 2, 3, 4], [-1]] # 图片名称

# images = [[array_to_image('./icon/%d.bin' % i) for i in range(1, 5)],

# [array_to_image('./icon/%d.bin' % -1)]]

labels = [['不对不对!', '再给一次机会', '你好笨哦', '最后一次'], ['不会有的别想了!', '哈哈哈哈承认了吧', '略略略略略']] # 文本标签内容

def __init__(self, parent=None):

super().__init__()

self.title('不会吗?')

self.parent = parent

self.geometry('400x300')

self.create_widgets()

def create_widgets(self):

if ChildWindow.labels[0]:

file_num = ChildWindow.images[0][0]

ChildWindow.images[0].remove(file_num)

load = Image.open('%d.jpg' % file_num).resize((180, 180))

# load = ChildWindow.images[0][0]

ChildWindow.images[0].pop(0) # 使用一个删除一个

render = ImageTk.PhotoImage(load)

self.img = Label(self, image=render, width='100', height='100')

self.img.image = render

self.img.pack(expand=YES, fill=BOTH)

label = ChildWindow.labels[0][0]

ChildWindow.labels[0].remove(label)

self.label = Label(self, text=label, font=('微软雅黑', 16))

self.label.pack(pady=20, fill=X, padx=10)

self.yes_button = Button(self, text='不会', width='10', height='1', command=self.yes_command)

self.yes_button.pack(side='left', expand=True, padx=10, pady=10)

self.no_button = Button(self, text='会', width='10', height='1', command=self.no_command)

self.no_button.pack(side='right', expand=True, padx=10, pady=10)

else:

load = Image.open('-1.jpg').resize((180, 180))

# load = ChildWindow.images[1][0]

render = ImageTk.PhotoImage(load)

self.img = Label(self, image=render, width='100', height='100')

self.img.image = render

self.img.pack(expand=YES, fill=BOTH)

self.label = Label(self, text=ChildWindow.labels[1][0], font=('微软雅黑', 24))

self.label.pack(pady=30, fill=X, padx=10)

self.after(700, self.destroy)

def yes_command(self):

self.yes_button.destroy()

self.no_button.destroy()

self.img.destroy()

self.label.destroy()

self.label = Label(self, text=ChildWindow.labels[1][1], font=('微软雅黑', 16))

self.label.pack(pady=50, fill=X, padx=10)

self.label2 = Label(self, text=ChildWindow.labels[1][2], font=('幼圆', 10))

self.label2.pack(pady=50, padx=30, side=RIGHT)

self.after(1200, self.destroy)

return

def no_command(self):

no_window = ChildWindow(self)

self.wait_window(no_window)

self.destroy()

return

以上就是程序的主体部分,基本功能已经完成。但是,作为朋友玩的小玩意还有点瑕疵:图片文件是直接在文件夹中以.jpg格式出现的,是可以随便替换的

Python代码也是可以随便更改的

做人就是要有追求完美的精神!所以我们来进行两步优化: 图片文件转二进制(这样就看不出来是图片啦啦啦) python转exe

图片文件转二进制

本来我是想把图片直接用数组的形式保存到代码里,后面发现可以保存成二进制,感觉后者方便一点。 这里参考了 Python实现图片与数组的转化

直接上代码

图片转二进制

import numpy as np

import os

from PIL import Image

import pickle as p

def image_to_array(file_path):

result = np.array([]) # 新建numpy数组

image = Image.open(file_path).resize((180, 180)) # 打开

r, g, b = image.split() # 通道分离

r_arr = np.array(r).reshape(-1) # 每个通道展开成一维数组

g_arr = np.array(g).reshape(-1)

b_arr = np.array(b).reshape(-1)

result = np.concatenate((r_arr, g_arr, b_arr)) # 三个通道拼在一起

# 以原文件名+ .bin保存

file_name = os.path.basename(file_path).split('.')[0]

with open(file_name + '.bin', 'wb') as f:

p.dump(result, f)

print('ok')

从二进制文件读图片

def array_to_image(file_path):

with open(file_path, 'rb') as f:

image_array = p.load(f)

image_array = image_array.reshape(3, 180, 180)

r = Image.fromarray(image_array[0]).convert('L')

g = Image.fromarray(image_array[1]).convert('L')

b = Image.fromarray(image_array[2]).convert('L')

image = Image.merge('RGB', (r, g, b))

return image

这样就可以先用第一个函数把图片全部转为二进制文件,然后删掉图片:) 我这里给图片的二进制文件建了个单独的文件夹。 当然,主程序的读图代码也要修改,直接换成注释的部分即可。

Python 转 exe 文件

在命令提示符中输入pip install pyinstaller

进入工程目录下输入:pyinstaller -F -w gui.py

就可以在生成的dist文件夹下找到gui.exe啦

pyinstaller 的使用:-F 生成单独的可执行文件 -w 去掉运行时的黑色命令行窗口(一般调试时可以看到窗口的输出) -i 生成的可执行文件的图标,后面加图标地址 -h 帮助

图标大小必须是32*32,颜色256。 可以使用这个网站转换图片。

代码下载

如果你对后续的故事感兴趣

欢迎围观:

也欢迎关注我的沙雕学习公众号:

​一本正经的搬砖日常

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值