欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字“加群”,加入华为云线上技术讨论群;输入关键字“最新活动”,获取华为云最新特惠促销。华为云诸多技术大咖、特惠活动等你来撩!

Python开发GUI

今天一位从我公众号开始结识的朋友,询问关于如何快速编写一个exe工具的问题。由于功能简单且之前无相关GUI编程基础,为了快速完成开发,我向他推荐了easygui模块。

python作为胶水语言,几乎没有不能做的事情,但个人一直觉得在GUI开发方面python可以算作是短板了,为什么?因为性能…python的性能问题,往往出现在其他编程语言对其的鄙夷中。但不管如何python在GUI编程上,也是有大量优秀模块的

tkinter

也许有些人不知道这个模块,但如果你安装python后,使用过自带的IDLE,那么你就应该了解它。tkinter作为python自带的GUI模块,IDLE便是通过该模块开发的,也是我比较喜欢的一个模块

easygui

第一次了解这个模块,还是在小甲鱼的《零基础入门学习python》时学习的,该模块对Tkinter进行了二次封装,是的GUI操作变得更为简单,但同时也局限于表层的使用,

wxpython

wxpython是一个Python包装wxWidgets(这是用 C++ 编写),一个流行的跨平台GUI工具包。在wxPython API主要模块包括一个核心模块。

wxpython的优势在速运行速度较快,但编写起来较为复杂,而且界面美化效果较差…

PYQT5

Qt是一套跨平台的C++库,不论是C、Java还是Python,都可以通过它来实现GUI界面的开发。PyQt5是Qt v5的一套全面的Python绑定。它实现为超过35个扩展模块,并使Python能够在所有支持的平台(包括iOS和Android)上用作C ++的替代应用程序开发语言。

如果你对GUI编程非常感谢兴趣,可以用心学学这个模块,但如果你只是想快速的实现一些GUI的功能,我更推荐大家学习tkinter模块,为什么?

  1. tkinter作为python默认自带的模块库,无需单独安装

  2. tkinter相比于wxpython与pyqt在针对小工具的编程方面,更为高效

  3. tkinter在网上存在大量的快速入门教程

tkinter实战

为了证明tkinter的方便与高效,我将很早前在公司写的一个pythonGUI代码,将图片转化为素描画的小工具,晚上重写了一次,先给大家看看实现效果:

避坑指南

tktiner添加图片

大家看到,tktiner中附带了一个我的微信二维码,这里只是为了演示tkinter添加图片,没有丝毫推广的味道,哈哈…这里要注意下,tktiner在添加图片时,PhotoImage(file=’tmp.gif’)要求图片必须是.gif结尾的图片,否则就会报错:

_tkinter.TclError: couldn’t recognize data in image file

关于base64

大家看到我没有加载图片,而是通过base64提前转码好二进制文件后,再进行导入,这样我们打包的exe在使用时,就无需附带一个图片文件了!

import base64

with open('demo.gif','rb') as f:
data = f.read()
img = base64.b64encode(data)

tkinter打包

既然我们开发的是GUI工具,必须得打包成exe才更好玩啊!但是以往很正常的打包,这次居然报错了:

找了半天才发现,从python 3.6开始,enum34库不再与标准库兼容。该库也是不必要的,因此只需卸载它即可。
pip uninstall enum34

再次执行,大功告成!

总体代码

最后附上工具的整体代码,可供大家参考:

# -*- coding: utf-8 -*-
# @Author : 王翔
# @JianShu : 清风Python
# @Date : 2019/8/6 01:18
# @Software : PyCharm
# @version :Python 3.7.3
# @File : ChangeImage.py from tkinter.messagebox import *
from tkinter.filedialog import *
from tkinter import *
import base64
from PIL import Image, ImageFilter, ImageOps
import os img_bs64 = b'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' def dodge(a, b, alpha):
return min(int(a * 255 / (256 - b * alpha)), 255) def draw(dir_info, blur=25, alpha=1.0):
base_dir = os.path.dirname(os.path.abspath(__file__))
save_file_name = os.path.join(base_dir, 'final.png')
img = Image.open(dir_info)
img1 = img.convert('L') # 图片转换灰色
img2 = img1.copy()
img2 = ImageOps.invert(img2)
for i in range(blur):
img2 = img2.filter(ImageFilter.BLUR)
width, height = img1.size
for x in range(width):
for y in range(height):
a = img1.getpixel((x, y))
b = img2.getpixel((x, y))
img1.putpixel((x, y), dodge(a, b, alpha))
img1.save(save_file_name)
img1.show() class LoginPage(object):
def __init__(self, master=None):
self.root = master
self.root.geometry('%dx%d' % (420, 240))
self.page = Frame(self.root)
self.Dir = StringVar()
self.Port = StringVar()
self.path = StringVar()
self.dir_info = StringVar()
self.create_page() def create_page(self):
self.page.grid()
with open('tmp.gif', 'wb+') as f:
f.write(base64.b64decode(img_bs64))
self.photo = PhotoImage(file='tmp.gif')
os.remove('tmp.gif')
Label(self.page, text='''
公众号: 清风Python
作者 : 王翔
时间 :2019-08-06
工具 :Python 3.7.3 Tkinter
详情 : 将图片转化为素描画''', justify=LEFT).grid(row=0, column=0, columnspan=2, rowspan=1, stick=NW)
Label(self.page, text="图片路径").grid(row=3, column=0, sticky=W, pady=5)
self.dir_info = Entry(self.page, textvariable=self.path)
self.dir_info.grid(row=3, column=1, columnspan=1, padx=20)
Button(self.root, text="选择路径", command=lambda: self.select_path()).grid(row=0, column=0, sticky=S, padx=20,
pady=5)
Label(self.page, image=self.photo).grid(row=0, column=2)
Button(self.page, text='转换', command=self.login_check, width=10).grid(row=3, column=2, padx=10, pady=5) def select_path(self):
path_ = askopenfilename(filetypes=[("file", "*.*")])
self.path.set(path_) def login_check(self):
img_dir = self.dir_info.get()
if img_dir == "":
showinfo(title='错误', massage='路径错误')
else:
draw(img_dir) root = Tk()
root.title('素描画转化工具')
LoginPage(root)
root.mainloop()

The End

OK,今天的内容就到这里,如果觉得内容对你有所帮助,欢迎点击文章右下角的“在看”。

公众号回复素描,下载打包好的exe图片转素描话工具,一起玩玩吧….

期待你关注我的公众号清风Python,如果觉得不错,希望能动动手指转发给你身边的朋友们。

作者:清风Python

Python开发GUI工具介绍,实战:将图片转化为素描画!的更多相关文章

  1. Python开发GUI工具介绍,实战:将图片转化为素描画!【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  2. Python开发GUI实战:图片转换素描画工具!

    奋斗没有终点 好好学习72变,因为将来 没有人能替你阻挡81难 . 生如蝼蚁,当有鸿鹄之志: 命如纸薄,应有不屈之心 . ​ 今天被这句话触动了,所以开篇分享给大家.鸡汤有毒,但有时大家却靠它激励自己 ...

  3. 学习游戏服务器开发必看,C++游戏服务器开发常用工具介绍

    C++游戏服务器开发常用工具介绍 在软件开发过程中需要使用的工具类型实属众多,从需求建模到软件测试,从代码编译到工程管理,这些工具都对项目有着不可替代的作用.庄子有云,"吾生也有涯,而知也无 ...

  4. HTML5将图片转化成字符画

    HTML5将图片转化成字符画 字符画大家一定非常熟悉了,那么如何把一张现有的图片转成字符画呢?HTML5让这个可能变成了现实,通过canvas,可以很轻松实现这个功能.其实原理很简单:扫描图片相应位置 ...

  5. Bytom Kit开发辅助工具介绍

    Bytom Kit是一款为了帮助开发者更简单地理解Bytom的开发辅助工具,集合了校验.标注.解码.测试水龙头等功能. 该工具用python语言封装了一套比原的API和7个工具方法,如果有开发需求可以 ...

  6. Python开发爆破工具

    上一篇讲到了如何用Python开发字典,而当我们手里有了字典 就可以进一步去做爆破的任务了,可以用现成的工具,当然也可以自己写 接下来我就要一步一步来写爆破工具! 爆破MySQL: 想要爆破MySQL ...

  7. 智普教育Python培训之Python开发视频教程网络爬虫实战项目

    网络爬虫项目实训:看我如何下载韩寒博客文章Python视频 01.mp4 网络爬虫项目实训:看我如何下载韩寒博客文章Python视频 02.mp4 网络爬虫项目实训:看我如何下载韩寒博客文章Pytho ...

  8. Python包管理工具介绍

    常见的包管理工具及关系 setuptools -->distribute easy_install-->pip 1.distribute distribute是对标准库disutils模块 ...

  9. 基于 canvas 将图片转化成字符画

    字符画大家一定非常熟悉了,那么如何把一张现有的图片转成字符画呢? HTML5 让这个可能变成了现实,通过 canvas,可以很轻松实现这个功能. 其实原理很简单:扫描图片相应位置的像素点,再计算出其灰 ...

随机推荐

  1. CSPS 模拟 70

    考试结束看A了两题就有点遗憾开开心心地去颓废了 吐槽一下这局LRS开的有点睿智,SD当的有点累 T1跟前边一个T1挺像,打表也可以 T2智障dp,开滚动数组就不会被卡空间了 T3牛逼构造题,虽然不是很 ...

  2. Python文字转换语音,让你的文字会「说话」,抠脚大汉秒变撒娇萌妹

    作者 | pk 哥 来源公众号 | Python知识圈(ID:PythonCircle) APP 也有文字转换为语音的功能,虽然听起来很别扭,但是基本能解决长辈们看不清文字或者眼睛疲劳,通过文字转换为 ...

  3. 提升jmeter脚本编写效率的方法:Fiddler导出jmx文件

    有效提升编写JMeter脚本效率的方法 jmeter的脚本来源有以下几种:badboy录制.jmeter自带的录制功能.手动编写脚本(使用fiddler/wireshark来抓包,然后构造协议写脚本) ...

  4. 关于swoole 定时器有时候无法清除的解决方法

    关于swoole 定时器有时候无法清除的解决方法 有时候start里面写个定时器 有时候你关闭进程的时候 发现定时器还是可以进行 目前只有重启服务器才可以 清除 还有就是ps -ef | grep p ...

  5. Linux命令实战(五)

    1.显示/etc目录下,以非字母开头,后面跟了一个字母以及其他任意长度字符的文件或目录. [qiuhom@test ~]$ls -d /etc/[^[:alpha:]][[:alpha:]]* ls: ...

  6. C#索引器与数组的区别

    1.索引器的索引值类型不限定为整数 2.索引器允许重载 3.索引器不是一个变量 4.索引器以函数签名方式this标识,而属性采用名称来标识,名称可以任意 5.索引器不能使用static来进行声明,属性 ...

  7. 领扣(LeetCode)删除排序数组中的重复项 个人题解

    给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. 示例 1 ...

  8. Vue导入非模块化的第三方插件功能无效解决方案

    一.问题: 最近在写vue项目时,想引入某些非模块化的第三方插件时,总是发现会有报错.且在与本地运行插件测试对比时发现插件根本没有注入到jQuery中(console.log($.fn)查看当前jq有 ...

  9. 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式

    从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...

  10. Redis面试题详解:哨兵+复制+事务+集群+持久化等

    Redis主要有哪些功能? 1.哨兵(Sentinel)和复制(Replication) Redis服务器毫无征兆的罢工是个麻烦事,如何保证备份的机器是原始服务器的完整备份呢?这时候就需要哨兵和复制. ...