python开发桌面应用步骤
前言
之前开发一些软件,亚马逊商品分析相关软件,但是基本上是通过程序猿控制台命令启动,同时在启动之前,还要进行程序依赖包,这对于非开发人员而言,简直是一种灾难, 为了让软件对于小白更加易用, 打算将其封装成应用程序(跨平台), 下面带大家一起完成python开发桌面应用的三步走. 在开始之前,我们先上效果图:
利用pygubu-designer设计UI页面
相对控制启动,桌面应用需要用户交互的ui, python有很多ui设计工具, 比如pygubu-designer、tkinter designer, 可以让一些用户通过拖拉方式,进行桌面UI设计.
pip install pygubu-designer
通过cmd等控制台打开设计器
pygubu-designer
就可以打开设计器
pip install pygubu
设计完成生成一个ui文件, 然后利用pygubu包解析ui文件,可以自动生成带有ui的应用程序
import sys
import os
import math
from concurrent.futures import ThreadPoolExecutor, as_completed
from logbook import Logger
import pygubu
from tkinter import messagebox
from settings import Platform_Code
from settings import Developer
import random
from util.computer_util import ComputerUtil
from util.license_util import LicenseHelper
from util.json_util import JsonParse
try:
DATA_DIR = os.path.join(os.path.abspath(os.path.dirname(os.path.dirname(__file__))), "static")
except NameError:
DATA_DIR = os.path.dirname(os.path.abspath(sys.argv[0]))
DEG2RAD = 4 * math.atan(1) * 2 / 360
class AmazonApplication:
def __init__(self):
self.log = None
self.platform = None
self.about_dialog = None
self.password = None
self.optionmenu_var = None
self.file_config = None
self.thread_pool = ThreadPoolExecutor(15) # 线程池个数
self.mission_list = []
self.license_helper = LicenseHelper()
self.config = None
self.platforms = {
}
self.builder = b = pygubu.Builder()
b.add_from_file(os.path.join(DATA_DIR, "ui", "amazon.ui"))
b.add_resource_path(os.path.join(DATA_DIR, "imgs"))
self.mainwindow = b.get_object("mainwindow")
self.mainmenu = b.get_object("mainmenu", self.mainwindow)
self.btn_menu = b.get_object("btn_menu")
self.func_menu = b.get_object("option_menu")
self.mainwindow.protocol("WM_DELETE_WINDOW", self.on_close_window)
b.connect_callbacks(self)
self.mainwindow.iconbitmap(os.path.join(DATA_DIR, "imgs", "amazon.ico"))
messagebox.showinfo(title='祝你满载而归', message='欢迎选择聚宝盆系统,使用有问题,请联系{}'.format(Developer))
b.import_variables(
self,
[
"password",
"file_config",
"optionmenu_var",
],
)
self.set_values()
pygubu 本身就是基于thinker进行二次封装的,Pygubu是一个基于Python的快速应用程序开发(RAD)工具,专为tkinter库打造,让开发者能够轻松地构建用户界面。这个强大的工具以其简洁易用的XML文件保存用户界面的设计,通过pygubu构建器动态加载到应用中,极大地提高了开发效率。
项目技术分析
Pygubu的核心是将XML作为用户界面设计的存储格式,这种数据结构允许直观地描述组件布局和属性。此外,它还提供了一个图形化的界面编辑器——pygubu-designer,使开发者可以像拖放一样创建和编辑用户界面。
在实现上,Pygubu依赖于Python 3.6或更高版本,并且很好地整合了tkinter和ttk(themed tkinter)模块,使得在保持性能的同时,也能获得美观的界面效果。不仅如此,Pygubu还提供了连接回调函数的功能,使得UI交互逻辑的编写更加简单。
编写spec文件,利用pyinstaller打包成可执行文件
完成以上工作之后, 我们就可以利用pyinstaller打包成可执行文件, pyinstaller是一个PyInstaller 是一个在Windows、GNU/Linux、macOS、FreeBSD、OpenBSD、Solaris 和AIX 下将Python 程序冻结(打包)为独立可执行文件的程序。
pip install pyinstaller
然后可以用它进行代码打包成可执行文件.值得注意的是,如果项目中是多文件,要使用spec文件管理打包方式,管理外界依赖.
# -*- mode: python -*-
encoding='UTF-8'
import os
path = os.getcwd()
import sys
import datetime
sys.path.append(path)
block_cipher = None
from util.io import get_file_list
from util.io import get_file_import
import site
code_dirs = ["config", "platforms", "extensions","restful","setting","util"]
code_files =[os.path.join(path,"amazon_app.py"),os.path.join(path,"settings.py"),os.path.join(path,'app','amazon_app.py')]
for second_path_dir in code_dirs:
new_dir = os.path.join(path, second_path_dir)
code_files.extend(get_file_list(new_dir,"py",[]))
print(code_files)
print("*****************************************************************")
# specify pygubu modules
hidden_imports = [
'pygubu.plugins.tk.tkstdwidgets',
'pygubu.plugins.ttk.ttkstdwidgets',
'pygubu.plugins.pygubu.dialog',
'pygubu.plugins.pygubu.editabletreeview',
'pygubu.plugins.pygubu.scrollbarhelper',
'pygubu.plugins.pygubu.scrolledframe',
'pygubu.plugins.pygubu.tkscrollbarhelper',
'pygubu.plugins.pygubu.tkscrolledframe',
'pygubu.plugins.pygubu.pathchooserinput',
#
# Uncomment the following module lines if you are using this plugins:
#
# awesometkinter:
# 'pygubu.plugins.awesometkinter.button',
# 'pygubu.plugins.awesometkinter.frame',
# 'pygubu.plugins.awesometkinter.label',
# 'pygubu.plugins.awesometkinter.progressbar',
# 'pygubu.plugins.awesometkinter.scrollbar',
# 'pygubu.plugins.awesometkinter.text',
# tkcalendar:
# 'pygubu.plugins.tkcalendar.calendar',
# 'pygubu.plugins.tkcalendar.dateentry',
# tkintertable:
# 'pygubu.plugins.tkintertable.table',
# tksheet:
# 'pygubu.plugins.tksheet.sheet',
# ttkwidgets:
# 'pygubu.plugins.ttkwidgets.calendar',
# 'pygubu.plugins.ttkwidgets.autocomplete',
# 'pygubu.plugins.ttkwidgets.checkboxtreeview',
# 'pygubu.plugins.ttkwidgets.color',
# 'pygubu.plugins.ttkwidgets.font',
# 'pygubu.plugins.ttkwidgets.frames',
# 'pygubu.plugins.ttkwidgets.itemscanvas',
# 'pygubu.plugins.ttkwidgets.linklabel',
# 'pygubu.plugins.ttkwidgets.scaleentry',
# 'pygubu.plugins.ttkwidgets.scrolledlistbox',
# 'pygubu.plugins.ttkwidgets.table',
# 'pygubu.plugins.ttkwidgets.tickscale',
# tkinterweb:
# 'pygubu.plugins.tkinterweb.htmlwidgets',
]
hidden_dirs = ["platforms","setting","config"]
for second_path_dir in hidden_dirs:
new_dir = os.path.join(path, second_path_dir)
hidden_imports.extend(get_file_import(new_dir,second_path_dir,"py",[]))
print(hidden_imports)
print("-------------------hidden_imports----------------------------")
pypi_package = site.getsitepackages()
third_package = None
for i in pypi_package:
if "site-packages" in i:
third_package = i
break
datas = [(os.path.join(path,'static'),'static')]
if third_package:
dddd_ocr = (os.path.join(third_package, 'ddddocr'),'ddddocr')
datas.append(dddd_ocr)
print(datas)
print("-------------------datas----------------------------")
a = Analysis(code_files,
pathex=[path],
binaries=[],
datas=datas,
hiddenimports=hidden_imports,
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='amazon',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False , icon='static\\imgs\\amazon.ico')
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='amazon-'+ str(datetime.date.today()))
构建好spec文件之后,可以通过cmd命令,快速打包好
pyinstaller amazon.spec --noconfirm