GUI布局Tkinter完善Python小项目

时间:2022-09-06 07:45:47

GUI布局Tkinter完善Python小项目

本次 Python 小项目主要功能:调用电脑摄像头实现拍照,并使用百度 API 接口实现图像识别。

上次完成了API的封装,这次完成GUI的布局。具体成品如下所示。

GUI布局Tkinter完善Python小项目

GUI布局Tkinter完善Python小项目

拍照保存图片采用的是opencv中的imwrite方法,具体的示例查看上上篇文章。

Tkinter 布局逻辑中最推荐使用的Grid布局。实现机制是将Widget逻辑上分割成表格,在指定的位置放置想要的Widget就可以了。

Grid布局参数说明

GUI布局Tkinter完善Python小项目

具体main.py代码如下。

""

@Author:Runsen 

@WeChat:RunsenLiu 

@微信公众号:Python之王 

@CSDN:https://blog.csdn.net/weixin_44510615 

@Github:https://github.com/MaoliRUNsen 

@Date:2020/11/29 

""

import time 

import cv2 as cv  # pip install opencv-python 

import tkinter as tk 

from tkinter import ttk  # 下拉框依赖库 

from tkinter import scrolledtext  # 滚动文本框依赖库 

from tkinter import N,E,S,W 

# 引入Baidu_API类 (上次文章) 

from baidu_api import Baidu_API 

 

# 拍照 

def take_a_photo(): 

    # 调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2 

    cap = cv.VideoCapture(0) 

    img_path = str(int(time.time())) + '.jpg' 

    while True

        # 从摄像头读取图片 

        sucess, img = cap.read() 

        # 转为灰度图片 

        # gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)# 

        # 显示摄像头 

        cv.imshow('----------please enter "s" to take a picture----------', img) 

        # 保持画面的持续,无限期等待输入 

        k = cv.waitKey(1) 

        if k == 27: 

            # 通过esc键退出摄像 

            cv.destroyAllWindows() 

            break 

        elif k == ord("s"): 

            # 通过s键保存图片,并退出。 

            cv.imwrite(img_path, img) 

            cv.destroyAllWindows() 

            break 

    # 关闭摄像头 

    cap.release() 

    # 打印日志 

    scr.insert(tk.END'[{}]拍摄成功...\n'.format(time.strftime('%Y-%m-%d %H:%M:%S'))) 

    # 返回图像 

    return img_path 

 

----------图形界面各个组件功能的设计---------- 

# 清除窗口日志 

def clear_the_window(): 

    scr.delete(1.0, tk.END

 

# 退出软件 

def exit(): 

    win.quit() 

 

# 下拉框选项选择 

def select_ttk(event): 

    global numberChosen 

    # 颜值评分 

    if numberChosen.current() == 1: 

        # 获取图像 

        img_path = take_a_photo() 

 

        try: 

            # 向API发送图像并获取信息 

            score, age, gender, race = Baidu_API().face_detect(img_path=img_path) 

 

            # 打印日志 

            scr.insert(tk.END'[{}]年龄「{}」性别「{}」人种「{}」\n'.format(time.strftime('%Y-%m-%d %H:%M:%S'), age, gender, race)) 

            scr.insert(tk.END'[{}]颜值评分为:{}/100 分\n'.format(time.strftime('%Y-%m-%d %H:%M:%S'), score)) 

        except

            scr.insert(tk.END'[{}]{}'.format(time.strftime(time.strftime('%Y-%m-%d %H:%M:%S')), 

                                               Baidu_API().face_detect(img_path=img_path))) 

    # 手势识别 

    if numberChosen.current() == 2: 

        scr.insert(tk.END'[{}]请将您的手势放置摄像头前...\n'.format(time.strftime('%Y-%m-%d %H:%M:%S'))) 

        time.sleep(0.1) 

        img_path = take_a_photo() 

        try: 

            classname_en, classname_zh = Baidu_API().gesture(img_path=img_path) 

            scr.insert(tk.END

                       '[{}]手势大意:{}({})\n'.format(time.strftime('%Y-%m-%d %H:%M:%S'), classname_zh, classname_en)) 

        except

            scr.insert(tk.END

                       '[{}]{}\n'.format(time.strftime('%Y-%m-%d %H:%M:%S'), Baidu_API().gesture(img_path=img_path))) 

    # 智能人脸抠图 

    if numberChosen.current() == 3: 

        scr.insert(tk.END'智能人脸抠图\n'.format(time.strftime('%Y-%m-%d %H:%M:%S'))) 

        img_path = take_a_photo() 

        out_path = str(int(time.time())) + '.jpg' 

        try: 

            Baidu_API().body_seg(img_path=img_path, out_path=out_path) 

            scr.insert(tk.END'完成智能人脸抠图'

        except

            scr.insert(tk.END'[{}]{}\n'.format(time.strftime('%Y-%m-%d %H:%M:%S'), 

                                                 Baidu_API().body_seg(img_path=img_path, out_path=None))) 

 

 

-------------创建窗口-------------- 

win = tk.Tk() 

win.title('客官先关注微信公众号:Python之王!'

win.geometry('600x300'

 

------------窗口组件设计----------- 

# grid中的参数:column, columnspan, in, ipadx, ipady, padx, pady, row, rowspan,sticky 

 

# 下拉框组件 

number = tk.StringVar 

numberChosen = ttk.Combobox(win, textvariable=number) 

numberChosen['value'] = ('please select''给我的颜值打个分吧!''识别一下我的手势''智能人脸抠图'

 

numberChosen.current(0)  # 设置默认值为第一个,即默认下拉框中的内容 

 

numberChosen.grid(row=1, column=1, rowspan=1, sticky=N + E + S + W) 

# 下拉框触发动作 (绑定点击事件) 

numberChosen.bind('<<ComboboxSelected>>', select_ttk) 

 

# 清除按钮组件 

tk.Button(win, cnf={'text''clear''command': clear_the_window}).grid(row=1, column=2, ipadx=1, sticky=N + E + S + W) 

 

# 退出按钮组件 

tk.Button(win, cnf={'text''exit''command': exit}).grid(row=1, column=3, ipadx=1, sticky=N + E + S + W) 

 

# 滚动文本框组件 

scr = scrolledtext.ScrolledText(win) 

scr.grid(row=2, column=1, columnspan=3, rowspan=1) 

 

# 使窗口一直显示 

win.mainloop() 

最后使用Pyinstaller打包即可。

Java 一次编译到处运行,Python没有这么好本事,Python有一个pyinstaller可以打包exe,在window平台下运行,这也是Python非常不好的方面,而且打包出来的占用内存非常的大

安装:pip install pyinstaller。Pyinstaller具体参数如下所示。

GUI布局Tkinter完善Python小项目

注意点:有的时候在代码最后面加上input(),这样打开exe不会一散而过。由于上面代码本身就是窗口一直显示,无需加上input()。

在打包时候,并没有提示错误,可以顺利打包成 exe 文件。但是在运行打包好的软件时,会提示找不到模块,本人遇到的是找不到第三方模块,例如 cv2 。这时候需要在打包时指定 -p 参数,后面跟上 python 目录下的第三方库模板目录路径 site-packages ,再打包就成功了。

cd 到代码的目录执行 pyinstaller main.py -F -p F:\anaconda\Lib\site-packages如果Pyinstaller打包报错numpy.core.multiarray failed to import,这是numpy和opencv的不兼容,可以降低numpy的版本。

原文地址:https://mp.weixin.qq.com/s/HjgRpGs1P_ltqci2IP2_2g