首页 > 其他分享 >4.29

4.29

时间:2024-06-19 18:11:26浏览次数:7  
标签:canvas window 4.29 range fun oval row

实验目的

l  使学生综合运用图形用户界面设计的概念;

l  使学生熟悉使用中间面板,组成层次复杂的GUI界面;

l  使学生掌握Python图形绘制和图像处理步骤与方法;

l  使学生掌握Python可视化处理的步骤、方法与编程;

实验环境及实验准备

l  所需硬件环境为微机;

l  所需软件环境为Python 3.X等;

l  掌握Python下界面容器与基本组件的基本知识与应用;

l  掌握Python下事件处理模型;

l  掌握Python下图形绘制的方法;

实验内容

(一)、设计实现电子算盘,并完成测试

【题目描述】

给小朋友设计一个电子算盘。要求绘制电子算盘界面,设计并实现打珠算过程(界面参考如下图示)。

界面右侧要求以图形绘制的方式绘制自画像,注意不能是图像文件显示的形式。

 

【源代码程序】

from tkinter import *

def initWindow():
    rect = canvas.create_rectangle(25, 40, 450, 400, width=5)       算盘边框
    
x0, y0, x1, y1 = 0, 0, 0, 0

    line_fenge = canvas.create_line(25, 100, 450, 100, width=5)     生成上下珠的分割线
    
x0, y0, x1, y1 = 0, 0, 0, 0
    for i in range(5):  生成5个上珠
        
top_oval[i] = canvas.create_oval(40 + x0, 60 + y0, 100 + x1, 90 + y1, fill='orange', tags=f"top{i}")
        x0 += 80
        x1 += 80
    x0, y0, x1, y1 = 0, 0, 0, 0
    for i in range(4):  生成4*5个下珠
        
for j in range(5):
            below_oval[i][j] = canvas.create_oval(40 + x0, 160 + y0, 100 + x1, 190 + y1, fill='yellow', tags=f"below{i}{j}")
            chushi[i][j] = canvas.coords(below_oval[i][j])
            x0 += 80
            x1 += 80
        x0 = 0
        x1 = 0
        y0 += 60
        y1 += 60
    print(chushi)
    num = [[0 for i in range(5)] for j in range(4)]  五个下珠分别对应的数值
    
num2 = [0 for i in range(5)]  五个上珠分别对应的数值
    
canvas.create_oval(750, 370, 470, 90, fill='yellow')
    canvas.create_oval(500, 170, 560, 200, fill='black')
    canvas.create_oval(650, 170, 710, 200, fill='black')

    canvas.create_arc(500, 200, 700, 300, start=-150, extent=120, style=ARC, width=5)
def get_empty():
    empty = [[0 for j in range(5)] for i in range(4)]
    for i in range(4):
        for j in range(5):
            if canvas.coords(below_oval[i][j]) != chushi[i][j]:
                empty[i][j] = 1
    print(empty)
    return empty

def bind():
    def handler_adaptor(handler, fun, row, col):
        """事件处理函数的适配器,相当于中介,可以帮助tag_bind函数传递参数"""
        
return lambda event, handler=handler, fun=fun, col=col, row=row: handler(event=event, fun=fun, row=row, col=col)

    def handler_adaptor2(handler2, fun, row):
        """事件处理函数的适配器,相当于中介,可以帮助tag_bind函数传递参数"""
        
return lambda event, handler2=handler2, fun=fun, row=row: handler2(event=event, fun=fun, row=row)

    def handler(event, fun, row, col):
        """下珠上划"""
        
content = fun       这个就是被点击的算珠id
        
empty = get_empty()
        if row == 0:
            if float(canvas.coords(content)[1]) - 40 >= 100:
                canvas.move(content, 0, -40)
        else:
            if empty[row - 1][col] == 1:
                if float(canvas.coords(content)[1]) - 40 >= 110 + 10 * (row + 1):
                    canvas.move(content, 0, -40)

    def handler2(event, fun, row):
        """上珠上划"""
        
content = fun       这个就是被点击的算珠id
        
if float(canvas.coords(content)[1]) - 20 >= 40:
            canvas.move(content, 0, -20)

    def handler3(event, fun, row, col):
        """下珠下划"""
        
content = fun       这个就是被点击的算珠id
        
empty = get_empty()
        if row == 3:
            if float(canvas.coords(content)[1]) + 40 <= 350:
                canvas.move(content, 0, 40)
        else:
            if empty[row][col] == 1:
                canvas.move(content, 0, 40)

    def handler4(event, fun, row):
        """上珠下划"""
        
content = fun       这个就是被点击的算珠id
        
if float(canvas.coords(content)[1]) + 20 <= 60:
            canvas.move(content, 0, 20)

    for i in range(5):
        canvas.tag_bind(top_oval[i], "<Button-1>", handler_adaptor2(handler2, fun=top_oval[i], row=i))
        canvas.tag_bind(top_oval[i], "<Button-3>", handler_adaptor2(handler4, fun=top_oval[i], row=i))
    for i in range(4):
        for j in range(5):
            canvas.tag_bind(below_oval[i][j], "<Button-1>", handler_adaptor(handler, fun=below_oval[i][j], row=i, col=j))
            canvas.tag_bind(below_oval[i][j], "<Button-3>", handler_adaptor(handler3, fun=below_oval[i][j], row=i, col=j))

if __name__ == "__main__":
    window = Tk()
    window.title("电子算盘")
    window.geometry("800x500")
    canvas = Canvas(window, width="800", height="500", bg="white")
    canvas.pack()
    top_oval = [int for i in range(5)]  定义列表存储5个上珠
    
below_oval = [[int for i in range(5)] for i in range(4)]  定义列表存储4*5个下珠
    
chushi = [[0 for j in range(5)] for i in range(4)]  所有下珠的初始坐标
    
initWindow()
    bind()
    window.mainloop()

【运行测试

 

(二)、以(一)中的电子算盘为基础,设计并实现珠算测试器,并完成测试。

【题目描述】

给小朋友设计一个珠算测试器,要求能够完成珠算加减法的测试。具体的要求功能如下:

(1)    用户启动测试,输入用户名后系统随机生成特定数目的加减法测试题;

(2) 要求测试使用表盘式或数字时秒表进行界面计时显示(参考如上图示);

(3) 对于每道测试题目,要求用户使用电子算盘完成珠算过程,当按下确认键时,将珠算结果与正确答案比对,并在界面上显示总题数、已答题数和已做对题数;

(4) 当测试完成,界面显示本次测试情况(包括用户名、测试题目及答题明细、对错情况、测试用时和测试成绩)

【源代码程序】

from tkinter import *
import tkinter.messagebox as msg
from random import randint

def initWindow():
    rect = canvas.create_rectangle(25, 40, 450, 400, width=5)       算盘边框
    
x0, y0, x1, y1 = 0, 0, 0, 0
    line_fenge = canvas.create_line(25, 100, 450, 100, width=5)     生成上下珠的分割线
    
x0, y0, x1, y1 = 0, 0, 0, 0
    for i in range(5):  生成5个上珠
        
top_oval[i] = canvas.create_oval(40 + x0, 60 + y0, 100 + x1, 90 + y1, fill='orange', tags=f"top{i}")
        x0 += 80
        x1 += 80
    x0, y0, x1, y1 = 0, 0, 0, 0
    for i in range(4):  生成4*5个下珠
        
for j in range(5):
            below_oval[i][j] = canvas.create_oval(40 + x0, 160 + y0, 100 + x1, 190 + y1, fill='yellow', tags=f"below{i}{j}")
            chushi[i][j] = canvas.coords(below_oval[i][j])
            x0 += 80
            x1 += 80
        x0 = 0
        x1 = 0
        y0 += 60
        y1 += 60
    global start_button, label_sum, username, entry_username, username_text, window_showusername
    global label_time, window_time, window_question
    global var_username, var_question, var_msg, window_answer, window_msg
    sum = Label(window, width=20, height=2, bg="#FFFFFF", textvariable=var, font=('Arial', 14))
    label_sum = canvas.create_window(750, 80, window=sum, anchor=NE)
    canvas.itemconfigure(label_sum, state="hidden")

    button = Button(window, width=10, height=2, bg="grey", text="开始测试吧!", command=adjust)
    start_button = canvas.create_window(750, 300, window=button, anchor=NE)

    text = Label(window, text="用户名:", width=10, height=2, bg="white")
    username_text = canvas.create_window(500, 200, window=text, anchor=CENTER)

    username = Entry(window, font=('Arial', 14))
    entry_username = canvas.create_window(640, 200, window=username, anchor=CENTER)

    label_showusername = Label(window, textvariable=var_username, width=15, height=2, bg="#FFFFFF", font=('Arial', 14))
    window_showusername = canvas.create_window(770, 0, window=label_showusername, anchor=NE)
    canvas.itemconfigure(window_showusername, state="hidden")

    label_time = Label(window, width=10, height=2, bg="#FFFFFF", font=('Arial', 14))
    window_time = canvas.create_window(600, 0, window=label_time, anchor=NE)
    canvas.itemconfigure(window_time, state="hidden")

    label_question = Label(window, width=30, height=2, bg="#FFFFFF", font=('Arial', 14), textvariable=var_question)
    window_question = canvas.create_window(630, 180, window=label_question, anchor=CENTER)
    canvas.itemconfigure(window_question, state="hidden")

    answer_button = Button(window, width=10, height=2, bg="grey", text="提交答案", command=judge, font=('Arial', 14))
    window_answer = canvas.create_window(630, 400, window=answer_button, anchor=CENTER)
    canvas.itemconfigure(window_answer, state="hidden")

    msg_label = Label(window, width=30, height=6, bg="#FFFFFF", font=('Arial', 14), textvariable=var_msg)
    window_msg = canvas.create_window(630, 260, window=msg_label, anchor=CENTER)
    canvas.itemconfigure(window_msg, state="hidden")

def run_time(target):
    def counting():
        global time
        time += 1
        global li
        print(li)
        if li != 5:
            target.config(text=f"所用时间:{str(time)}s")
        else:
            target.config(text="游戏结束")
        target.after(1000, counting)  间隔1000毫秒再次执行counting函数
    
counting()

def adjust():
    global ques, li, true, false, all_username
    myusername = username.get()
    all_username = myusername
    if myusername != "":
        """对画布中的部件进行一些调整"""
        for i in range(5):
            ques[i] = get_question()
        canvas.itemconfigure(label_sum, state="normal")
        canvas.itemconfigure(window_showusername, state="normal")
        canvas.itemconfigure(window_time, state="normal")
        canvas.itemconfigure(window_question, state="normal")
        canvas.itemconfigure(window_answer, state="normal")
        canvas.itemconfigure(window_msg, state="normal")
        var_question.set(f"问题:{ques[0][0]}")
        run_time(label_time)
        var_username.set(f"用户名:{myusername}")
        sum = get_sum()
        var.set(f"当前数值:{sum}")
        var_msg.set(f"总题数:5\n已经做了0题\n已做对0题\n已做错0题")
        canvas.itemconfigure(start_button, state="hidden")
        canvas.itemconfigure(entry_username, state="hidden")
        canvas.itemconfigure(username_text, state="hidden")
    else:
        msg.showinfo("错误", "用户名不能为空白")
def judge():
    def next():
        var_question.set(f"问题:{ques[li][0]}")
    global li, false, true
    sum = get_sum()
    myanw[li][0] = ques[li][0]
    myanw[li][1] = sum
    if sum == int(ques[li][1]):
        true += 1
        msg.showinfo("答案正确", f"恭喜你做对了")
    else:
        false += 1
        msg.showinfo("答案错误", f"做错了!正确答案是{ques[li][1]}")
    li += 1
    var_msg.set(f"总题数:5\n已经做了{li}题\n已做对{true}题\n已做错{false}题")
    if li != 5:
        next()
    else:
        msg.showinfo("游戏结束", f"以下是你的战绩\n总题数:5\n总用时:{time}s\n总成绩:{true * 20}分\n做对了{true}题\n做错了{false}题")
        msg.showinfo("游戏结束", f"{all_username},你好\n以下是你的答题明细\n总题数:5\n1.{myanw[0][0]}={myanw[0][1]}\n"
                                 f"2.{myanw[1][0]}={myanw[1][1]}\n3.{myanw[2][0]}={myanw[2][1]}\n"
                                 f"4.{myanw[3][0]}={myanw[3][1]}\n5.{myanw[4][0]}={myanw[4][1]}\n")
        exit()

def get_question():
    answer, num1, num2 = 0, 0, 0
    operator = ""
    temp = randint(1, 2)
    if temp == 1:
        while 1:
            num1 = randint(0, 99999)
            num2 = randint(0, 99999)
            if num1 + num2 <= 99999:
                break
        answer = num1 + num2
        operator = "+"
    elif temp == 2:
        while 1:
            num1 = randint(0, 99999)
            num2 = randint(0, 99999)
            if num1 - num2 > 0:
                break
        answer = num1 - num2
        operator = "-"
    equation = str(num1) + operator + str(num2)
    return equation, answer
def get_sum():
    sum = 0
    temp = 5
    for i in range(5):
        temp -= 1
        if num2[i] == 1:
            sum += 10 ** temp * 5
    temp = 5
    for j in range(5):
        temp -= 1
        for i in range(4):
            if num[i][j] == 1:
                sum += 10 ** temp
    return sum

def bind():
    def handler_adaptor(handler, fun, row, col):
        """事件处理函数的适配器,相当于中介,可以帮助tag_bind函数传递参数"""
        
return lambda event, handler=handler, fun=fun, col=col, row=row: handler(event=event, fun=fun, row=row, col=col)

    def handler_adaptor2(handler2, fun, row):
        """事件处理函数的适配器,相当于中介,可以帮助tag_bind函数传递参数"""
        
return lambda event, handler2=handler2, fun=fun, row=row: handler2(event=event, fun=fun, row=row)

    def handler(event, fun, row, col):
        """下珠上划"""
        
content = fun       这个就是被点击的算珠id
        
if row == 0:
            if float(canvas.coords(content)[1]) - 40 >= 100 and num[row][col] == 0:
                canvas.move(content, 0, -40)
                num[row][col] = 1
        else:
            if num[row - 1][col] == 1:
                if float(canvas.coords(content)[1]) - 40 >= 110 + 10 * (row + 1) and num[row][col] == 0:
                    canvas.move(content, 0, -40)
                    num[row][col] = 1
        sum = get_sum()
        var.set(f"当前数值:{sum}")

    def handler2(event, fun, row):
        """上珠上划"""
        
content = fun       这个就是被点击的算珠id
        
if float(canvas.coords(content)[1]) - 20 >= 40:
            canvas.move(content, 0, -20)
            num2[row] = 1
        sum = get_sum()
        var.set(f"当前数值:{sum}")

    def handler3(event, fun, row, col):
        """下珠下划"""
        
content = fun       这个就是被点击的算珠id
        
if row == 3:
            if num[row][col] == 1:
                canvas.move(content, 0, 40)
                num[row][col] = 0
        else:
            if num[row + 1][col] == 0 and num[row][col] == 1:
                canvas.move(content, 0, 40)
                num[row][col] = 0
        sum = get_sum()
        var.set(f"当前数值:{sum}")

    def handler4(event, fun, row):
        """上珠下划"""
        
content = fun       这个就是被点击的算珠id
        
if float(canvas.coords(content)[1]) + 20 <= 60:
            canvas.move(content, 0, 20)
            num2[row] = 0
        sum = get_sum()
        var.set(f"当前数值:{sum}")

    for i in range(5):
        canvas.tag_bind(top_oval[i], "<Button-1>", handler_adaptor2(handler2, fun=top_oval[i], row=i))
        canvas.tag_bind(top_oval[i], "<Button-3>", handler_adaptor2(handler4, fun=top_oval[i], row=i))
    for i in range(4):
        for j in range(5):
            canvas.tag_bind(below_oval[i][j], "<Button-1>", handler_adaptor(handler, fun=below_oval[i][j], row=i, col=j))
            canvas.tag_bind(below_oval[i][j], "<Button-3>", handler_adaptor(handler3, fun=below_oval[i][j], row=i, col=j))

if __name__ == "__main__":
    window = Tk()
    window.title("电子算盘")
    window.geometry("800x500")
    canvas = Canvas(window, width="800", height="500", bg="white")
    canvas.pack()
    ques = [0 for i in range(5)]
    myanw = [[0, 0]for i in range(5)]
    li = 0
    time, true, false = 0, 0, 0
    start_button, label_sum, username, entry_username = 0, 0, 0, 0
    username_text, window_showusername, window_time = 0, 0, 0
    label_time, window_question, window_answer = 0, 0, 0
    all_username = ""
    window_msg = 0
    var = StringVar()
    var_username = StringVar()
    var_question = StringVar()
    var_msg = StringVar()
    top_oval = [int for i in range(5)]  定义列表存储5个上珠
    
below_oval = [[int for i in range(5)] for i in range(4)]  定义列表存储4*5个下珠
    
chushi = [[0 for j in range(5)] for i in range(4)]  所有下珠的初始坐标
    
num = [[0 for i in range(5)] for j in range(4)]  # 4*5个下珠分别是否被拨动
    
num2 = [0 for i in range(5)]  五个上珠分别是否被拨动
    
initWindow()
    bind()
    window.mainloop()

【运行测试

 

实验分析及问题思考

查找资料,结合实例代码,至少比较三种Python图形处理库或图像处理库的异同点。

【答案】1. Pillow (Pillow Imaging Library)

特点:

易用性:Pillow 是 Python Imaging Library (PIL) 的一个分支,专为简单图像处理任务设计,如基本的裁剪、旋转、滤镜应用等。

文件格式支持广泛:支持多种图像格式的读写,包括常见的 JPEG、PNG、BMP 等。

基本操作:适合于图像的加载、保存、显示、基本变换等。

实例代码(打开并显示图片):

1from PIL import Image

2

3# 打开图像

4img = Image.open('example.jpg')

5# 显示图像

6img.show()

2. OpenCV (Open Source Computer Vision Library)

特点:

计算机视觉:OpenCV 是一个强大的计算机视觉库,特别适合于实时图像处理、视频分析、特征检测、机器学习等高级应用。

性能:底层用 C++ 编写,提供了高效的算法,适合于计算密集型任务。

高级功能:包含人脸检测、物体识别、图像分割等高级功能。

实例代码(灰度转换):

1import cv2

2

3# 读取图像

4img = cv2.imread('example.jpg')

5# 转换为灰度图像

6gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

7# 显示图像

8cv2.imshow('Gray Image', gray_img)

9cv2.waitKey(0)  # 等待按键后关闭窗口

10cv2.destroyAllWindows()

3. scikit-image

特点:

科学图像处理:scikit-image 面向科学研究和工程应用,提供了一系列高级算法,如图像分割、几何变换、滤波、形态学处理等。

与科学计算库集成:与 NumPy、SciPy 紧密集成,便于进行复杂的数学运算和数据分析。

模块化:提供模块化的设计,易于扩展和定制。

1from skimage import io, exposure

2

3# 读取图像

4img = io.imread('example.jpg')

5# 直方图均衡化

6eq_img = exposure.equalize_hist(img)

7# 显示图像

8io.imshow(eq_img)

9io.show()

异同点总结

易用性和目标用户:Pillow 最为简单直观,适合初学者和基本图像处理需求;OpenCV 功能强大且深入,更适合于计算机视觉和复杂图像分析;scikit-image 则侧重于科研和工程领域的高级图像处理。

性能:OpenCV 由于其底层的 C++ 实现,在处理速度上通常优于其他两个库,特别是在大规模图像处理和视频处理时。

功能范围:Pillow 覆盖了基本的图像处理操作;OpenCV 包含更多计算机视觉相关的高级功能;scikit-image 则提供了大量科学图像分析的工具。

社区和文档:三个库都拥有活跃的社区和良好的文档支持,但因为 OpenCV 和 scikit-image 的专业性,相关资源可能更偏向于特定领域。

标签:canvas,window,4.29,range,fun,oval,row
From: https://www.cnblogs.com/szm123/p/18256977

相关文章

  • 4.29
    依然是讨厌的周一学习内容:安卓<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical"  a......
  • 4.29
    packagecom.example.test_one;importandroidx.appcompat.app.AppCompatActivity;importandroid.content.Intent;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.EditText;importandroid.widget.Toast;importcom.example.test_one.dao.UserDao......
  • 腾讯公益赛个人冲刺博客5(2024.4.29)
    今天调整了帮扶功能前端页面,略微比之前好看了一些<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:to......
  • 上周热点回顾(4.29-5.5)
    热点随笔:· 博客园商业化之路-开发任务众包平台:召集早期合作开发者 (博客园团队)· 一个开源轻量级的C#代码格式化工具(支持VS和VSCode) (追逐时光者)· .NET开源、功能强大、跨平台的图表库-LiveCharts2 (追逐时光者)· 微软开源MS-DOS「GitHub热点速览」 (削微寒)·......
  • 腾讯公益赛团队冲刺博客5(2024.4.29)
    未完成sos后端、在线医生、聊天室进行中细化帮扶功能的后端和数据库,调整前端页面已完成sos第一个页面、帮扶前端,登陆注册、主页 ......
  • 云原生周刊:K8s 中的服务和网络 | 2024.4.29
    开源项目推荐k8s-image-swapperk8s-image-swapper是Kubernetes的一个变更Webhook,它将镜像下载到自己的镜像仓库,并将镜像指向该新位置。它是dockerpull-throughproxy的一个替代方案。KubeIPv2KubeIPv2是DoiTKubeIPv1-main开源项目的全面改进版本,最初由AvivLau......
  • 2024.4.29鲜花/校庆
    正文若干年后,星际旅行和永生技术已经成为现实,\(214\)岁的我在一颗名为XY星的星球上成为了星际新闻局局长。记得那天是幻想历元年四月二十九日,我在审核今天的新闻稿时发现了这样一篇报道:XMSY中学即将迎来\(110\)周年校庆...一个破学校的校庆能出现在星际新闻上,很奇怪吧......
  • Flow(网络流 written on 4.29)
    前言Classtakenon4.2Writtenon4.29Flow解决问题类网络流是用有向图每条边来模拟流动,有流量限制的情况下,求解最大流量(有时以及最小费用)的问题。同时也是将各类问题(尤其匹配问题)通过建模为网络流来用网络流算法求解的一个方法。解决问题的一般特点:数据范围不大不小,\(......
  • 闲话 4.29:伯特兰定理及另一道题
    伯特兰公设任意\(\ge4\)的正整数\(n\)满足:存在一个质数\(p\in(n,2n)\)。以下\(p\)均取质数,\(p_i\)表示第\(i\)个质数。引理1:\[\prod_{p\len}p\le4^n,n>1\]首先有一个想法:\[\ln\prod_{p\len}p\le\pi(n)\lnn\simn\len\ln4\]这些放缩是相当松的,因为......
  • 2024.4.29
    2024.4.29【锦水汤汤,与君长诀!】Monday三月二十一数论专题同余oi.wiki!除法定理对于任何整数a,和正整数m,存在唯一整数q,r,使得满足\(0\ler<m,a=qm+r\)其中$$q=\lfloor\frac{a}{m}\rfloor$$为商,\(r=a\mod\m\)为余数余数将amodm记作余数同余如果\(a\mo......