首先描述一下需求:
在开始时,有按钮“选择文件”,点击后能自动打开文件夹选中图片文件,选中文件后,点击“确定”按钮,打开子界面,展示图片和颜值评分。具体如图所示(先说好,图片随便找的,可不是本人,我哪有那么丑,我可是当地吴彦祖,啊哈哈哈哈):
OK,画饼充饥,饼已经画好了,下面是具体实现。
首先说第一个选择图片文件的界面怎么实现。
这个比较简单。首先布置好条条框框:
root = tk.Tk()
root.title("GUI")
fm1=tk.Frame(root)
path = tk.StringVar()
Ltop=tk.Label(fm1,text="请选择图片路径")
B1=tk.Button(fm1, text = "路径选择", command =selectPath)
E1=tk.Entry(fm1, textvariable =path,bd=5)
# imagePath=path.get()
B2=tk.Button(fm1, text = "确定", command =lambda:secondWindow(path.get()))
Ltop.pack(side = tk.TOP)
B1.pack(side=tk.LEFT)
E1.pack(side = tk.LEFT)
B2.pack(side=tk.LEFT)
fm1.pack(side=tk.TOP)
root.mainloop()
第一行相当于建立了最底层的一个大画布,以后所有条条框框都是在这个画布上搞。fm1=tk.Frame相当于建立了一块小画布。Ltop就是用来显示文字的。
path:对于tkinter来说,你想显示一些字符串并不是仅仅写一个字符串变量就行了,而是需要tk的stringvar类以及其set方法。
B1是一个按钮,按钮上面写的是“路径选择”,如果你点击了这个按钮,那么就会执行selectPath这个函数。
E1是一个输入文本框,这里我们把输入的文字直接用选中的文件路径来赋值了。
B2也是一个按钮,按钮文字为“确定”,点击按钮时,会执行secondWindow(path.get())函数,其实也就是用来布局子界面的函数。
以上是定义了一些条条框框,但还没告诉系统到底这些条条框框应该放在具体哪个位置,谁在前谁在后。下面就开始布局了。
先布局的Ltop,他的位置是在一个界面的最顶部(tk.Top),我们在初始化Ltop的时候,第一个参数是fm1,所以Ltop是在fm1这块小画布的最顶部。
然后布局B1,E1,B2。因为B1,E1,B2在初始化时,第一个参数都是fm1,所以B1,E1,B2都是在fm1这块小画布的最左边。都在最左边那不是重叠了么?不是,tkinter的这种布局是与语句顺序有关的。相当于B1在最最最左边,E1挨着B1在左边(即E1在B1的右边),B2在E1的右边,但大家都在一个水平线上。
最后布局fm1,因为初始化fm1时,参数是root,所以意思是fm1这块小画布(以及小画布上面的所有组件)在root这块画布的最顶部。
然后root.mainloop()。
这里面说得很轻松,但其实有很多坑。比如如何理解tk.Frame这个函数,command =lambda:secondWindow(path.get())这里为什么要用lambda。想要深入了解的可以查看我的博客:tkinter Frame函数形象化解析,tkinter command函数带参数不带参数的区别。
下面是定义selectPath和secondWindow两个函数了。
selectPath比较简单:
def selectPath():
path_ = filedialog.askopenfilename()
path.set(path_)
这里filedialog.askopenfilename是tkinter中自带的函数。功能为文件选择框,返回值为你选定文件的绝对路径。
path之前以前提到了,是stringvar的对象,set方法是字符串赋值了,我们也可以使用path.get来获得字符串。
然后是secondWindow(为了少让大家费眼读代码,这里只放示意代码了):
def secondWindow(imagePath):
# print("进入:",imagePath)
win=tk.Toplevel()
panel = tk.Label(win) # initialize image panel
win.config(cursor="arrow")
getImage(imagePath,panel) # 用于在gui界面上显示图片
'''
定义组件,然后进行组件位置设定
'''
panel.pack(padx=10, pady=10)
win.mainloop()
这里需要的注意的是,子界面必须要是tk.Toplevel。secondWindow调用了getImage函数,具体实现如下:
def getImage(imagePath,panel):
img=cv2.imread(imagePath)
cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA) # 转换颜色从BGR到RGBA
current_image = Image.fromarray(cv2image) # 将图像转换成Image对象
imgtk = ImageTk.PhotoImage(image=current_image)
panel.imgtk = imgtk
panel.config(image=imgtk)
这里需要注意的是,cv2.imread中的imagePath不能含有中文字符,否则就会报出类似这样的错误:
cv2.error: OpenCV(4.0.0) C:\projects\opencv-python\opencv\modules\imgproc\src\color.cpp:181: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor
然后我们就完成整个项目了!写完肯定是喜悦的,但是如何把自己的喜悦分享给别人。特别是那些本地没有配置环境的人呢?
我将在 Python 打造颜值评分应用(三):使用pyinstaller打包应用 介绍如何使用pyinstaller把python文件打包成win10应用。