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()

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


游戏首页

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

在这里插入图片描述


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

首先创建一个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()


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

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()

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


下面这个方法就可以让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)

游戏首页完整代码

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()

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

猜你喜欢

转载自blog.csdn.net/qq_59142194/article/details/125524456