• Python GUI案例之看图猜成语开发(第一篇)


    Python GUI案例之看图猜成语开发(第二篇)
    Python GUI案例之看图猜成语开发(第三篇)
    Python GUI案例之看图猜成语开发(完结篇)


    前言

    由于之前写的这篇博文https://blog.csdn.net/qq_59142194/article/details/123937365?spm=1001.2014.3001.5501)对ttkbootstrap做了个简单地使用方法介绍,并且也得到了许多小伙伴的收藏。所以这次就用ttkbootstrap来做一个简单的看图猜成语小游戏的开发来对它有一个综合地认识。
    好了,首先我们在开发前,还需要收集一些看图猜成语对应的素材,所以我们需要用一个爬虫程序来爬一波图片。这里我直接就在度娘上随便找了一个网站进行爬取的(看图猜成语用到的网址:http://www.hydcd.com/cy/fkccy/index.htm)。

    准备好成语图片素材后,我们将准备要实现这些功能:

    • 一,游戏首页页面:在首页页面里需要实现绘制一个看图猜成语文字的标题,定义两个按钮功能(开始游戏,退出游戏),还有一个输入游戏昵称的功能并且要对昵称进行验证是否为空,才能开始游戏;
    • 二,游戏选择模式页面:在首页点击开始游戏后,进入游戏的选择模式页面,分为训练模式和闯关模式两种;
    • 三,游戏训练模式页面:将成语图片加载后,只实现猜成语功能(一张图片,一个输入框,一个按钮)和回答的准确率;
    • 四,游戏闯关模式页面:将实现自定义有多少个关卡数,16个汉字提示(12个随机生成的干扰汉字),游戏通关记录所用的时间。

    本次实现这些功能主要用到的库有:

    • ttkbootstrap
    • requests

    效果实现

    在这里插入图片描述
    (注:本文所用到的图片素材均来自网上
    素材提取:https://download.csdn.net/download/qq_59142194/85827790

    了解完这些后,就让我们开始吧!


    爬取素材篇

    这里就不详细介绍爬取的过程了,是一个简单的爬虫,没有反爬!!!但是从这个网站上爬取下来的图片有点小(120 x 120),使其图片在gui上加载时很小,不太好看。所以我简单地用了PIL对图像进行放大处理(300 x 300)这样加载出图片就会好看些。好了,直接上代码。

    import requests
    import re
    import os
    import time
    from PIL import Image
    from fake_useragent import UserAgent
    
    # 爬取成语图片
    def SpiderIdiomPictures():
        cookies = {
            'BAIDU_SSP_lcr': 'https://www.baidu.com/link?url=58oz4AEVxDWXanBqrfF95dogUPcAVAktBQT0uBu8o4rGPY4J4Kg_-DsmJdvTHryfy8pdGnnOjDG54qbh82KB7K&wd=&eqid=ecc1cb040001afcc0000000662a84cc7',
            'Hm_lvt_8754302607a1cfb0d1d9cddeb79c593d': '1654580566,1655196891',
            'Hm_lpvt_8754302607a1cfb0d1d9cddeb79c593d': '1655200014',
        }
        headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'Pragma': 'no-cache',
            'Referer': 'http://www.hydcd.com/cy/fkccy/index3.htm',
            'Upgrade-Insecure-Requests': '1',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36',
        }
        if not os.path.exists('./看图猜成语'):
            os.mkdir('./看图猜成语')
        idx = 0
        for page in range(1,11):
            print(f'\n\033[31m<<<第{page}页爬取中……>>>\033[0m')
            if page == 1:
                page = ''
            url = f'http://www.hydcd.com/cy/fkccy/index{page}.htm'
            session = requests.session()
            response = session.get(url=url, cookies=cookies, headers=headers)
            response.encoding = response.apparent_encoding
            ###解析图片url(http://www.hydcd.com/cy/fkccy/images/CF91100-50.png)和成语
            for i in re.findall('<img border="0" src="(.*?)"></p>',response.text):
                result = i.split('"')
                if len(result) > 2:
                    img_url = f'http://www.hydcd.com/cy/fkccy/{result[0]}'  #图片url
                    idiom_name = result[2] #图片名字(成语名)
                    if len(idiom_name) == 4:
                        headers['User-Agent'] = UserAgent().Chrome
                        with open(f'./看图猜成语/{idiom_name}.png','wb') as f:
                            f.write(session.get(img_url,headers=headers).content)
                        print(f'{idiom_name}.png 保存成功!!!')
                        time.sleep(0.3)
                        idx += 1
    
        print(f'\n抓取完毕!!!\n总共抓取\033[31m{idx}张\033[0m图片')
    
    # 图片放大
    def ImageProcessingBig():
        print(f'\n\033[31m<<<开始将图片进行放大>>>\033[0m')
        for imgfile in os.listdir('./看图猜成语/'):
            if len(imgfile.split('.')) == 2:
                # 待处理图片路径
                img_path = Image.open('./看图猜成语/'+imgfile)
                # resize图片大小,入口参数为一个tuple,新的图片的大小
                img_size = img_path.resize((300, 300))
                # 处理图片后存储路径,以及存储格式
                imgname = imgfile.split('.')[0]
                img_size.save(f'./看图猜成语/{imgname}.png')
        print(f'\n\033[31m<<<所有图片已放大完成!!!>>>\033[0m')
    
    if __name__ == '__main__':
        # 爬取网站上的成语图片(http://www.hydcd.com/cy/fkccy/index.htm),图片大小120x120
        SpiderIdiomPictures()
        # 把爬取到的所有图片放大(300x300)
        ImageProcessingBig()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    看图猜成语小程序开发(第一篇)


    游戏首页

    游戏首页页面:在首页页面里需要实现绘制一个看图猜成语文字的标题,定义两个按钮功能(开始游戏,退出游戏),还有一个输入游戏昵称的功能并且要对昵称进行验证是否为空,才能开始游戏。
    效果实现:

    在这里插入图片描述


    导包
    import ttkbootstrap as ttk
    import sys,os,random,threading,time,datetime
    from ttkbootstrap.constants import *
    from ttkbootstrap.dialogs import Messagebox,Querybox
    
    • 1
    • 2
    • 3
    • 4

    首先创建一个ttkbootstrapWindow类,主要用来实例化创建应用程序窗(root)、窗口居中、让窗口显示出来,以便后面的类来继承这个类。
    class ttkbootstrapWindow:
        # 实例化创建应用程序窗口
        root = ttk.Window(title="看图猜成语", themename="litera", resizable=(False, False))
        # 让窗口居中
        def window_middle(self,windowwidth,windowheight):
            screenwidth = self.root.winfo_screenwidth()
            screenheight = self.root.winfo_screenheight()
            locx = int((screenwidth - windowwidth) / 2)
            locy = int((screenheight - windowheight) / 2)
            self.root.geometry("{}x{}+{}+{}".format(windowwidth, windowheight, locx, locy))
        # 显示窗口
        def window_displaymodule(self):
            self.root.mainloop()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    然后就可以开始写首页里面的东西了。

    class guessIdiomsFromPictures(ttkbootstrapWindow):
        def __init__(self):
            super().__init__()
            self.index()
            self.window_displaymodule()
    
        # 首页内容
        def index(self):
            self.window_middle(windowwidth=960,windowheight=540) #窗口大小宽x高(960 x 540),默认居中
            self.index_frame = ttk.Frame(self.root)
            self.index_frame.pack(fill=BOTH,expand=YES)
            self.bg_img = ttk.PhotoImage(file='./sucai/index_bg.png')
            self.bg_img_Label = ttk.Label(self.index_frame, image=self.bg_img)
            self.bg_img_Label.pack(fill=BOTH, expand=YES)
            self.title_lable = ttk.Label(self.bg_img_Label, text='  看图猜成语', font=('华文行楷', 56, 'italic'), cursor='watch',background='#E7CBB5', bootstyle=WARNING, width=14)
            self.title_lable.place(x=190, y=80)
            self.begin_button_img = ttk.PhotoImage(file='./sucai/beginGame.png')
            self.begin_button = ttk.Button(self.index_frame, bootstyle=(SUCCESS, "outline-toolbutton"),image=self.begin_button_img, command=self.begin_game)
            self.begin_button.place(x=270, y=310)
            self.exit_button_img = ttk.PhotoImage(file='./sucai/exitGame.png')
            self.exit_button = ttk.Button(self.index_frame, bootstyle=(SUCCESS, "outline-toolbutton"),image=self.exit_button_img, command=self.exit_game)
            self.exit_button.place(x=480, y=320)
            ttk.Label(self.bg_img_Label, text='请输入昵称:', cursor='watch', bootstyle=DARK).place(x=250, y=212)
            self.entry_nickname = ttk.Entry(self.index_frame, show=None, font=('微软雅黑', 16))
            self.entry_nickname.insert('0', "暴龙战士之王")
            self.entry_nickname.place(x=340, y=200, width=360, height=50)
    		# self.index_move()
        # 验证昵称是否为空
        def index_verify(self):
            self.nickname = self.entry_nickname.get().strip()
            if self.nickname:
                return True
            else:
                return False
        # 开始游戏
        def begin_game(self):
            try:
                if not self.index_verify():
                    Messagebox.show_info(message="请先输入您的昵称!")
                    return
                print('开始游戏')
            except: pass
        # 退出游戏
        def exit_game(self):
            sys.exit()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    但是,如果这样写,这些组件都是静态布局的,效果感受也没有那么好,所以我们需要再写一个方法来使部分组件能过到达移动的动态效果。


    下面这个方法就可以让self.title_lable、self.begin_button、self.exit_button
    实现移动的效果,把这个方法加到guessIdiomsFromPictures类里面并在里面的index方法最后面调用就行了。

    # 页面组件移动
        def index_move(self):
            def run(rate):
                rate += 5
                button_posy = 540 - rate*1.5
                self.begin_button.place(x=270,y=button_posy)
                self.exit_button.place(x=480,y=button_posy+10)
                if rate < 80:
                    self.title_lable.place(x=190, y=rate)
                    self.title_lable.after(60,run ,rate % 80)
                elif 80<= rate < 150:
                    self.title_lable.after(60, run, rate % 150)
                else:
                    ttk.Label(self.bg_img_Label, text='请输入昵称:', cursor='watch', bootstyle=DARK).place(x=250, y=212)
                    self.entry_nickname.insert('0', "暴龙战士之王")
                    self.entry_nickname.place(x=340, y=200, width=360, height=50)
            run(0)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    游戏首页完整代码

    import ttkbootstrap as ttk
    import sys
    from ttkbootstrap.constants import *
    from ttkbootstrap.dialogs import Messagebox
    
    class ttkbootstrapWindow:
        # 实例化创建应用程序窗口
        root = ttk.Window(title="看图猜成语", themename="litera", resizable=(False, False))
        # 让窗口居中
        def window_middle(self,windowwidth,windowheight):
            screenwidth = self.root.winfo_screenwidth()
            screenheight = self.root.winfo_screenheight()
            locx = int((screenwidth - windowwidth) / 2)
            locy = int((screenheight - windowheight) / 2)
            self.root.geometry("{}x{}+{}+{}".format(windowwidth, windowheight, locx, locy))
        # 显示窗口
        def window_displaymodule(self):
            self.root.mainloop()
    
    # 看图猜成语
    class guessIdiomsFromPictures(ttkbootstrapWindow):
        def __init__(self):
            super().__init__()
            self.index()
            self.window_displaymodule()
        # 首页内容
        def index(self):
            self.window_middle(windowwidth=960,windowheight=540) #窗口大小宽x高(960 x 540),默认居中
            self.index_frame = ttk.Frame(self.root)
            self.index_frame.pack(fill=BOTH,expand=YES)
            self.bg_img = ttk.PhotoImage(file='./sucai/index_bg.png')
            self.bg_img_Label = ttk.Label(self.index_frame, image=self.bg_img)
            self.bg_img_Label.pack(fill=BOTH, expand=YES)
            self.title_lable = ttk.Label(self.bg_img_Label, text='  看图猜成语', font=('华文行楷', 56, 'italic'), cursor='watch',background='#E7CBB5', bootstyle=WARNING, width=14)
            self.begin_button_img = ttk.PhotoImage(file='./sucai/beginGame.png')
            self.begin_button = ttk.Button(self.index_frame, bootstyle=(SUCCESS, "outline-toolbutton"),image=self.begin_button_img, command=self.begin_game)
            self.exit_button_img = ttk.PhotoImage(file='./sucai/exitGame.png')
            self.exit_button = ttk.Button(self.index_frame, bootstyle=(SUCCESS, "outline-toolbutton"),image=self.exit_button_img, command=self.exit_game)
            self.entry_nickname = ttk.Entry(self.index_frame, show=None, font=('微软雅黑', 16))
            self.index_move()
        # 页面组件移动
        def index_move(self):
            def run(rate):
                rate += 5
                button_posy = 540 - rate*1.5
                self.begin_button.place(x=270,y=button_posy)
                self.exit_button.place(x=480,y=button_posy+10)
                if rate < 80:
                    self.title_lable.place(x=190, y=rate)
                    self.title_lable.after(60,run ,rate % 80)
                elif 80<= rate < 150:
                    self.title_lable.after(60, run, rate % 150)
                else:
                    ttk.Label(self.bg_img_Label, text='请输入昵称:', cursor='watch', bootstyle=DARK).place(x=250, y=212)
                    self.entry_nickname.insert('0', "暴龙战士之王")
                    self.entry_nickname.place(x=340, y=200, width=360, height=50)
            run(0)
        # 验证昵称是否为空
        def index_verify(self):
            self.nickname = self.entry_nickname.get().strip()
            if self.nickname:
                return True
            else:
                return False
        # 开始游戏
        def begin_game(self):
            try:
                if not self.index_verify():
                    Messagebox.show_info(message="请先输入您的昵称!")
                    return
                print('开始游戏')
            except: pass
        # 退出游戏
        def exit_game(self):
            sys.exit()
    
    if __name__ == '__main__':
        guessIdiomsFromPictures()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    今天的内容就先写到这里吧,喜欢的小伙伴们记得点赞收藏一下哈!!!

  • 相关阅读:
    MySQL数据库之主从复制及读写分离
    【Java挑战赛】——static、代码块
    Nginx之正则表达式、location匹配简介及rewrite重写
    MySQL高级篇知识点——数据库其它调优策略
    LLVM MC layer框架说明
    HD系列边缘网关,助力工商业储能发展!
    SOCKS5 认证的方法
    详细聊聊Vue中设计的computed和watch
    spring 微服务nacos未授权访问漏洞修复
    springboot 整合 nacos 作为注册中心
  • 原文地址:https://blog.csdn.net/qq_59142194/article/details/125524456