从开始有想法学习python到现在也大概半年了,断断续续的一直再看,主要是:廖雪峰Python链接如下:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
一些python基础语法,安装都从上边学习,到目前为止,基础语法学习完成了,应用还得多写代码,编辑工具使用的Notpad++,IO,多线程,Web,网络都还没看,随后估计会看网络和IO,Web有兴趣再看了。
最近几天在弄,Python图形化界面,由于之前拿Qt开发,习惯了信号与槽的消息机制,所以知道有pyqt之后就开始研究了。Python的图形化界面库还挺多的,我只说说我接触过的两个。TKinter和Pyqt5。
tkinter库: Python自带库,放一个我写的小demo
调用:
from tkinter import *
import tkinter.messagebox as messagebox
类:
class Application(Frame):
def __init__(self,master = None):
Frame.__init__(self,master)
self.pack()
self.createWidgets()
def input_One(self,num):
print("Input",num)
def createWidgets(self):
self.nameInput = Entry(self)
self.nameInput.pack(side = TOP,padx=10,pady=10)
self.atButton = Button(self,text='Hello',bg = "red",fg = "black",command = self.hello)
self.atButton.pack()
self.m_photo = PhotoImage(file = "D:\Python\\66logo.png")
self.m_label = Label(self,text = "Python学习",font = ('Arial', 15),bg= "blue",fg = "red",width = 240,height = 200,compound = CENTER)
self.m_label.pack(side = RIGHT,padx= 60,pady = 60)
self.image_label = Label(self.m_label,image = self.m_photo).grid(row = 0)
# self.image_label.place(in_ = self.m_label,relx = 0.5,rely = 0.5,anchor =CENTER,x =-58,y=-55)
# self.image_label.pack(side = TOP,padx = 20,pady=20)
# ax = -58
# ay = -55
row_x = 1
row_y = 1
for i in range(1,10):
if i <=3:
if i ==1:
# ax = -58
row_y = 1
else:
# ax += 20
row_y+=1
# ay = -35
row_x = 1
elif i > 3 and i<=6:
if i == 4:
# ax = -58
row_y = 1
else:
# ax+=20
row_y +=1
# ay = -5
row_x = 2
elif i>6 and i<=9:
if i == 7:
# ax = -58
row_y = 1
else:
# ax+=20
row_y += 1
# ay = 25
row_x = 3
print(i)
self.One_Btn = Button(self.m_label,text=str(i),command = lambda:self.input_One(i),width = 2,height = 1).grid(row=row_x,column = row_y )
# self.Two_Btn = Button(self,text="two").grid(row = 4,column)
#self.One_Btn.place(in_ = self.m_label,relx = 0.5,rely = 0.5,anchor =CENTER,x =ax,y=ay)
def hello(self):
name = self.nameInput.get() or 'world'
if name == 'quit':
print('quit')
messagebox.showinfo('Message','hello,%s' % name)
类的部分不做释意了,就说一下思路,按照教程写了一个基础UI界面,Entry,然后按钮弹出提示框,如果有输入则提示框显示“Hello,str”,否则提示“Hello,world”。后来,在Label里边,写了显示文字,显示图片。然后准备做一个计算器。
这时候发现了问题,或者是我接触时间短不知道怎么解决。界面布局,tkinter有三种,pack(),grid(),place()。布局分类不能像Qt一样,自由设置Label内部图片显示位置,坐标,写法比较僵硬。如果Label设置为父控件,子控件在放置Label或者其他,为了设置图片位置,我将图片放置与一个子Laebl中,然后在设置子label在父Label中的位置。尝试了pack(),grid(),place(),说一下对这三个的理解,
pack(),侧重于方位布局,LEFT,RIGHT,TOP等,然后可以通过padx,pady设置偏离位置。
grid(),模块自动计算行列位置,将窗口或者父控件按比列划分,类似于Excel表格。可以自由设置行列位置,区块类布局比较方便。
place(),用于设置绝对位置。
感觉对与布局的细节设置不是很方便,比较繁琐。
另外一个,消息机制,目前我还没弄懂。比如说:button的按键响应事件
self.One_Btn = Button(self.m_label,text=str(i),command = lambda:self.input_One(i),width = 2,height = 1).grid(row=row_x,column = row_y )
其中:按键响应函数如下command = lambda:self.input_One(i)按钮,执行input_One(i)函数时,本意是这样,通过for循环,创建好9个按钮,都绑定input_One(i),执行函数时,每个传参应该都不一样,我想自动获取按键对应的编号,暂时没有找到函数获取。按理说,每一次绑定的执行函数时,i的值都是唯一确定,但是打印消息时,发现i的值,临时获取,最后一个i的值,暂时没想到解决方法。
界面调用部分:
app = Application()
app.master.geometry('400x300')
app.master.resizable(width=False, height=False)
app.master.title('Hello World')
app.mainloop()
Pyqt5:安装
python都默认安装好,环境也都配置好。
**error:This application failed to start because it could not find or load the Qt platforms plugins**
解决方法:安装python时一定要注意,中文路径的问题,最好不要有中文路径,否则会出现如上错误,安装好pyqt5之后。
安装好python之后,安装pyqt5之前一定要注意,先升级pip,更新到最新版本:
进入cmd:输入命令:
python -m pip install --upgrade pip
第二步,升级sip,升级到匹配版本。
命令如下:
pip3 uninstall sip
第三步:安装pyqt5
命令行如下:
pip3 install pyqt5
等待安装完成后,即可使用pyqt5。其实还有一个问题,因为我是之前一直拿Qt开发,qt库都很全,所以相关工具库我都没有下载配置。如果第一次安装pyqt,则需要安装qttools。
命令如下:
pip install PyQt5-tools
全部安装完成后即可使用了。
测试代码:
import sys
from PyQt5 import QtWidgets, QtCore
app = QtWidgets.QApplication(sys.argv)
widget = QtWidgets.QWidget()
widget.resize(360, 360)
widget.setWindowTitle("Hello, PyQt5!")
widget.show()
sys.exit(app.exec_())
由于我使用Notpad++,使用Qt设计师建好界面以后,每次更改都要使用如下命令将ui文件改为py文件
pyuic5 path/filename.ui -o path/filename.ui
所以写了如下代码,默认ui文件名字和工程文件名除后缀之外相同,且在同一目录下。例如:工程文件名为 code.py,UI文件名为 code.ui。
import os
import time
import sys
FileName = os.path.basename(sys.argv[0]) #sys.argv[0] 当前文件的绝对路径 os.path.basename 获得文件名字
FilePath = sys.argv[0].replace(FileName,"") #当前文件路径
UiName = FileName.replace(".py",".ui") #ui文件名字
UiPath = FilePath +UiName #ui文件路径
Ui_pyName = FilePath+"ui.py" #ui.py 文件的绝对路径
FileFlag = os.path.isfile(Ui_pyName) # 判断文件是否存在 1:存在 0:不存在
if FileFlag == 0:
sys_cmd = os.popen("pyuic5 "+UiPath+" -o "+Ui_pyName) #执行cmd命令将 ui文件转为py文件
time.sleep(1) #延时1S
FileName:工程文件名 code.py
FilePath:工程文件路径 D:\python\
UiName: UI文件名 code.ui
UiPath:UI文件路径 D:\python\
Ui_pyname:UI文件转化后的py文件绝对路径 : D:\python\ui.py
FileFlag : ui.py文件是否存在标志位,不存在,则新建。
当前判断ui.py是否存在,如果存在则不修改。但是不能够判断py是否为最新文件。 如果想保证每次更新可以改为
import os
import time
import sys
FileName = os.path.basename(sys.argv[0]) #sys.argv[0] 当前文件的绝对路径 os.path.basename 获得文件名字
FilePath = sys.argv[0].replace(FileName,"") #当前文件路径
UiName = FileName.replace(".py",".ui") #ui文件名字
UiPath = FilePath +UiName #ui文件路径
Ui_pyName = FilePath+"ui.py" #ui.py 文件的绝对路径
sys_cmd = os.popen("pyuic5 "+UiPath+" -o "+Ui_pyName) #执行cmd命令将 ui文件转为py文件
其实随后有一个想法,做一个Notpad++的插件,将如上功能集成到里边,目前正在研究。除去每次繁琐的配置修改。
下边是自己的写的一个Demo,按键显示。
import os
import time
import sys
FileName = os.path.basename(sys.argv[0])
FilePath = sys.argv[0].replace(FileName,"")
UiName = FileName.replace(".py",".ui")
UiPath = FilePath +UiName
Ui_pyName = FilePath+"ui.py"
FileFlag = os.path.isfile(Ui_pyName)
if FileFlag == 0:
sys_cmd = os.popen("pyuic5 "+UiPath+" -o "+Ui_pyName)
time.sleep(1)
print(Ui_pyName,UiPath,UiName) #打印调试信息
from PyQt5 import QtWidgets, QtGui
from ui import Ui_Form
class m_window(QtWidgets.QWidget,Ui_Form):
def __init__(self):
super(m_window,self).__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.hello) #Qt槽函数连接
def hello(self): #槽函数
self.label.setText("Hello world")
app = QtWidgets.QApplication(sys.argv)
window = m_window();
window.show()
sys.exit(app.exec_())