日常刷课,课程链接:Bilibili:Python Qt 图形界面编程 - PySide2 PyQt5 PyQt PySide
一些需要注意的事
该教程是PyQt图形界面基础,所用库为PySide2,但是用PyQt5也没有什么太多的不同,该基础阶段图形界面区别就有俩,
1.引入库文件时
由:
from PySide2.QtWidgets import QApplication, QMainWindow, 巴拉巴拉
改为:
from PyQt5.QtWidgets import QApplication, QMainWindow, 巴拉巴拉
2.动态加载UI文件时
由:
from PySide2.QtUiTools import QUiLoader
class Stats:
def __init__(self):
self.ui = QUiLoader().load('main.ui')
改为:
from PyQt5 import uic
class Stats:
def __init__(self):
self.ui = uic.loadUi("main.ui")
其他就没有什么不同了,可以正常食用
1. 封装代码
在不使用designer做图形化界面的时候需要定义所有的按钮、文本框等各种控件的名字、类型和尺寸位置颜色等,如果一股脑都写在def init(self):下面就有点丑,不能折叠,而且没有区分度,可以整个函数把界面定义的控件收进去,而且把一些不需要调用、修改、输入的控件和需要调用修改输入的控件(前面有self.的)分开,以后改代码和调用数据的时候就知道哪些是提示文字哪些是可调用的东西,看着也整齐点。
def __init__(self):
super().__init__()
#界面
self.myui() = uic.loadUi("a.ui")
#控件信号响应
self.button.clicked.connect(self.balabala)
def myui(self):
label1 = QLabel("巴啦啦", self)
label2 = QLabel("小魔仙", self)
self.button = QPushButton('乌卡拉卡', self.window)
def balabala(self)
#一些按钮功能实现
#…
app = QApplication([])
stats = Stats()
stats.window.show()
app.exec_()
2. 打包并发布程序
首先需要cd到.py文件所在目录下,如果有.ui,也需要把.ui文件放同级目录下。以下是命令们:
pyinstaller xxx.py --noconsole --hidden-import PyQt5.QtXml
这个代码可以封装带有动态导入的程序。--noconsole
是指定不要命令行窗口,如果程序打不开的话可以删掉这句,就会有命令行窗口跳出来了,就可以查看错误了;--hidden-import PyQt5.QtXml
是PyInstaller自己无法分析动态导入,所以跟它说一下它就知道了。
--icon="logo.ico"
后面加上这个可以让打包好的exe文件有设定好的图标,但不是界面的图标哦!就是exe程序的图标罢了,注意这里必须是.ico格式,网上到处都是图片转ico的免费地址随便找一个。
pyinstaller xxx.py --workpath d:\pybuild --distpath d:\pybuild\balabala
这串命令可以自己cd到.py文件所在的位置进行打包,distpath后面的路径里是你打包好的有用东西的文件夹,比如这个balabala,打开后有一个.py文件的名字命名(这里是xxx)的文件夹,这个文件夹里有好多程序,其中xxx.exe,是可执行程序,双击就可以运行,但是在别的电脑上运行的话需要整个xxx文件夹才行,其中这几个文件夹可以拿出来,其他的再建个文件夹放进去就行了,但是他们都要在同一个目录下。
base_library.zip
xxx.exe
xxx.exe.manifest
python36.dll
所以最后打包给别人的目录大概是这样:
–xxx(file)
| +其他文件的文件夹(file)
| base_library.zip
| xxx.exe
| xxx.exe.manifest
| python36.dll
2022.7.26编辑:哼,亲测打包不能这么打,这么打是运行不出来的!还是别改位置了乱点就乱点吧大不了让人家发送个桌面快捷方式就行了
3. 图形界面布局
总原则:先把所有需要的控件摆上去,再进行Layout,Layout从小到大进行。
在Layout完事之后会出现部分尺寸变丑的情况,再进行微调即可,实在是丑的调不动了就加个弹簧,又不是UI设计师,UI设计师咋可能用QT设计ui呢,反正不管设计出来的ui到底是怎么布局的都不会影响代码功能实现。
布局的意义我觉得有两点:
1.好看
2.方便修改外观
在设计各个控件外观时直接在layout好了的父布局或者祖父布局(神tm祖父布局)上改字体啊颜色大小边框距离之类的就行,可一键修改,但在全局修改的时候会出改了但看起来没变的小bug,只要保存了再重新打开就变了,问题不大。
4. 图形界面样式设计
就是字体大小颜色边框距离尺寸这些,有两种方法:
- 在界面上摁拖
- 属性编辑器-QWidge-styleSheet里输入样式更改语句
第一种方法就蒜了吧,直接看第二种,方法也很简单,就是在styleSheet后面的框里输入更改样式的语句,需要注意的是,这个方法可以用在每个布局上,也可以用在全局里每个有相同特征的控件,比如都是QLabel类,都叫bala的控件(同类控件名字不同,一般来说不同控件名字也尽量不同,但也可以相同,方便统一样式)等,具体格式如下:
xxx {
#样式语句
}
这里语句要有分号结尾,如果只有一条可以没分号,都带上蒜了!
如果只改一个控件的样式,直接在styleSheet后面输入样式语句就行,不需要花括号,当控件自身、父布局、祖父布局都有定义时,按照就近原则,也就是如果你爷爷让你去清华,你爸让你去北大,但是你就要去蓝翔,那么你最后就去的是蓝翔,他俩的话对你没用,每个子布局、单独控件都只继承该子布局、控件缺省的父布局样式,也就是如果你哥没有去哪的想法,那他就继承了你爸的想法去了北大,如果你爸对你俩都没有要求,那么他就会继承你爷爷的想法去清华。
5. 多线程
如果按照上面的思路已经可以做简单的程序并封装使用了,但是如果想要实现的功能需要久一点的时间,而这段时间你又想进行别的界面操作,就好比你设置了15分钟微波炉烤红薯,你还想去躺床上刷一会儿B站,就要多线程,否则当你按下微波炉启动按钮后的15分钟你什么都不许干,就尬在那等着红薯烤好才能干别的,这就是主线任务被支线任务卡死,烤不完红薯不能干别的,对应到程序里就是界面因一个计算卡死,不响应其他操作。
也比较简单,首先import Thread的库,没有这库就自己装
from threading import Thread
多线程的思路就是,在每个功能函数里设置接口接入一个线程入口函数,并传送用得到的变量,再把实现功能计算的代码放在线程入口函数下,由于这个线程入口函数和功能函数平级了,所以要把入口函数里要用到的变量什么的放后面括号里。
看着绕,用代码说明吧:
def balabala(self):
balabala #一些变量定义、前处理、等
s = balalbal
preoared = bala
#新建名为thread的线程入口,入口调用名为threadSend的线程函数
#并传递该线程需要用到的变量s和prepared
thread = Thread(target = self.threadSend, args= (s, prepared))
thread.start() #打开该thread线程入口
#定义线程函数干的事
def threadSend(self,s,prepared):
try:#能行行
r = s.send(prepared)
balabala
except:#不能行蒜了
balabala
结语
好了……大概就是这些了,具体用什么怎么调用不在基础课程内了,这个up声音挺好听的反正是那种听着不会困的声音,整体听下来可能也就是封装ui图标那块出了问题,我还没看到底怎么整,小问题以后再说!
每天学一点点,就能少菜一点点,加油( •̀ ω •́ )y