10天速通Tkinter库——Day8:《植物杂交实验室》杂交实验及历史记录界面

本文主要是介绍10天速通Tkinter库——Day8:《植物杂交实验室》杂交实验及历史记录界面,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本篇博客我将介绍Tkinter实践项目《植物杂交实验室》中的杂交实验、实验结果和历史记录两个页面的制作。

它们作为主窗口的子页面实例,除了继承主窗口的基础设置(如图标、标题、尺寸等等)、还可以使用主窗口的属性和方法(如数据变量self.hybridizationPlants、页面跳转方法switch_to_screen等等),以及在constants.py中的常量定义和tool.py中定义的通用组件。具体实现见博客10天速通Tkinter库——Day6:《植物杂交实验室》整体框架介绍

目录

1. 杂交实验

1.1 加载背景、返回按钮、关闭按钮 

1.2 初始化杂交实验信息

1.3 杂交实验开始按钮

1.4 选择重置按钮 

1.5 初始化基础植物卡片矩阵

1.6 初始化基础植物卡片选择结果矩阵

 1.7 杂交方式选择

1.8 杂交算法

2. 实验结果

3. 历史记录

3.1 类定义与初始化 

3.2 历史记录数据加载 

3.3 记录显示

one_item 方法

all_record 方法

4. 总结


1. 杂交实验

组件构成如下:

让我们一步一步来实现,定义一个ExperimentScreen类,继承了主界面和tk.Frame。

1.1 加载背景、返回按钮、关闭按钮 

class ExperimentScreen(tk.Frame):"""植物杂交系统1. 基础植物卡片矩阵2. 基础植物选择框3. 杂交方法选择4. 杂交实验开始"""def __init__(self, parent):super().__init__(parent)# 背景和基础组件self.breeding_background = create_background(self,experiment_background_path)self.close_button = close_button(self,close2_1_path,close2_2_path,clear=2)self.back_button = back_button(self,back2_1_path,back2_2_path,clear=2)
  • 初始化父类。
  • 创建了背景 breeding_background 。
  • 创建了关闭按钮 close_button 。
  • 创建了返回按钮 back_button 。

1.2 初始化杂交实验信息

        # 杂交信息self.card_choose_photo = [None for _ in range(4)]self.card_choose_photo_id = [0,0,0,0]self.card_choose_num = 0self.method_id = 0self.result_plant_id = 0   self.result = 0
  • self.card_choose_photo:一个包含 4 个元素的列表,用于存储选择的植物卡片。
  • self.card_choose_photo_id:一个包含 4 个元素的列表,用于存储选择的植物照片的 ID。
  • self.card_choose_num:选择的植物数量。
  • self.method_id:杂交方法的 ID。
  • self.result_plant_id:杂交结果植物的 ID。
  • self.result:杂交结果。

1.3 杂交实验开始按钮

        self.start_button = create_button(self,dark_image_path=start1_path,light_image_path=start2_path,width=351,height=103,locate_x=503,locate_y=455,command=self.on_start_button_click)

 定义了一个开始按钮,用于在选择植物和杂交方法后开始实验,它的点击事件处理函数如下:

    def on_start_button_click(self):"""开始杂交实验按钮点击事件"""if self.card_choose_photo_id[0]!=0 and self.method_id!=0:if (self.method_id==3 or self.method_id==4) and self.card_choose_photo_id[1]!=0:worning_music.play()messagebox.showinfo("提示", "该杂交方法只能选择单株植物!")self.on_clear_button_click()else:self.on_breeding_method_select()self.master.children['result_screen'].result_show(self.result,self.result_plant_id)self.on_clear_button_click()self.master.switch_to_screen('result_screen')elif self.card_choose_photo_id[0]!=0 and self.method_id==0:worning_music.play()messagebox.showinfo("提示", "请选择杂交方式!")else:worning_music.play()messagebox.showinfo("提示", "请选择基础植物!")

这段代码定义了一个名为 on_start_button_click 的方法,用于处理开始杂交实验按钮的点击事件。

  1. 检查条件

    • 首先检查 self.card_choose_photo_id 是否不为空(即玩家选择了基础植物)且 self.method_id 是否不为零(即玩家选择了杂交方法)。
    • 然后根据 self.method_id 的值进一步检查玩家的选择是否合理。
  2. 错误提示与处理

    • 如果 self.method_id 为 3 或 4(假设这代表特定的杂交方法),并且玩家选择了第二株植物(self.card_choose_photo_id[1] 不为零),则播放警告音乐并显示提示信息,告知只能选择单株植物进行该杂交方法。
    • 如果 self.method_id 为 3 或 4 且玩家未选择第二株植物,则播放警告音乐并显示提示信息,告知玩家需要选择单株植物进行该杂交方法。
    • 如果 self.method_id 为 0(即未选择杂交方法),则播放警告音乐并显示提示信息,告知玩家需要选择杂交方法。
    • 如果 self.card_choose_photo_id[0] 为零(即未选择基础植物),则播放警告音乐并显示提示信息,告知玩家需要选择基础植物。
  3. 执行杂交实验

    • 如果所有条件都满足,调用 self.on_breeding_method_select() 方法执行杂交实验的逻辑。
    • 调用 self.master.children['result_screen'].result_show(self.result,self.result_plant_id) 方法显示结果屏幕,并传递结果和植物ID。
    • 调用 self.on_clear_button_click() 方法清除当前屏幕的任何状态或选择。
    • 使用 self.master.switch_to_screen('result_screen') 方法切换到结果屏幕。

1.4 选择重置按钮 

        self.clear_button = create_button(self,dark_image_path=clearButton1_path,light_image_path=clearButton2_path,width=180,height=100,locate_x=590,locate_y=238,command=self.on_clear_button_click,)

定义了一个清空按钮,可以重置我们的选择,它的点击事件处理函数如下:

    def on_clear_button_click(self):"""清空组件,初始化基础植物选择和杂交方法"""self.card_choose_photo_id = [0,0,0,0]self.card_choose_num = 0self.method_id = 0for col in range(4):label = tk.Label(self.card_frame,image=self.empty_card,bd=0)label.grid(row=0, column=col,sticky="NSEW")      

 这段代码定义了一个名为 on_clear_button_click 的方法,用于处理清除按钮的点击事件。这个方法的主要功能是清空用户界面中与基础植物选择和杂交方法相关的所有组件,并初始化这些选择的状态。

  1. 初始化基础植物选择

    • self.card_choose_photo_id 是一个列表,用于存储用户选择的基础植物图片ID。列表长度为4,意味着它可以存储4个基础植物的选择状态。将列表中的所有元素初始化为0,表示没有选择任何基础植物。
  2. 初始化杂交方法选择

    • self.method_id 是一个变量,用于存储用户选择的杂交方法ID。将其初始化为0,表示没有选择任何杂交方法。
  3. 清空用户界面

    • 使用一个循环遍历 self.card_frame 中的每一列(共4列),这表明用户界面可能包含4个用于选择基础植物的组件。
    • 对于每一列,创建一个标签 (tk.Label),并设置其图像为 self.empty_card(一个空卡牌的图像)。这表示在用户选择基础植物之前,每个选择区域显示为空。
    • bd=0 设置标签的边界为0,使得标签看起来更简洁。
    • 使用 grid 方法将标签放置在界面上,其中 row=0 表示标签位于第一行,column=col 表示标签位于第 col 列,sticky="NSEW" 表示标签将填充其所在的格子,允许在所有方向上伸缩。

1.5 初始化基础植物卡片矩阵

这个和基础植物图鉴的实现方式相同,只是对点击事件进行了修改。

        self.card_button_matrix()
    def card_button_matrix(self):"""基础植物卡片矩阵"""card_frame = tk.Frame(self)card_frame.place(x=28,y=88)card_frame.config(bg="orange")for row in range(6):for col in range(8):button = tk.Button(card_frame, image=self.master.basal_plant_card[row][col])button.config(borderwidth=0,highlightthickness=0)button.grid(row=row, column=col,sticky="NSEW")def on_click(row, col):card_music.play()if self.card_choose_num ==4 :worning_music.play()messagebox.showinfo("错误", "你最多只能添加四种基础植物!")else:self.card_choose_photo_id[self.card_choose_num] = col+1+row*8self.card_choose_num += 1self.card_choose_frame()button.bind('<Button-1>', lambda event, r=row, c=col: on_click(r, c))

这段代码定义了一个名为 card_button_matrix 的方法,用于创建一个基础植物卡片矩阵,并处理卡片点击事件。 

  1. 创建卡片框架

    • card_frame = tk.Frame(self)
    • 创建一个 tk.Frame 实例,作为卡片矩阵的容器,并设置为其父容器 self
    • 使用 place 方法将 card_frame 放置在父容器中的特定位置 (x=28, y=88)
    • card_frame.config(bg="orange")
    • 设置 card_frame 的背景颜色为橙色。
  2. 填充卡片矩阵

    • 使用两个嵌套的 for 循环来遍历行和列,创建卡片按钮。
    • for row in range(6) 和 for col in range(8)
    • 在每个位置创建一个 tk.Button 实例,按钮的图片设置为 self.master.basal_plant_card[row][col],这是从主窗口对象中获取的植物卡片图片。
    • button.config(borderwidth=0,highlightthickness=0)
    • 设置按钮的边框宽度为0,高亮边框宽度也为0,使得按钮看起来没有边框。
    • button.grid(row=row, column=col,sticky="NSEW")
    • 使用 grid 布局管理器将按钮放置在卡片矩阵的相应位置,sticky="NSEW" 表示按钮会粘在单元格的东、南、西、北边缘。
  3. 处理点击事件

    • def on_click(row, col):
    • 定义一个局部函数 on_click,它接受行号 row 和列号 col 作为参数。
    • card_music.play()
    • 当按钮被点击时,播放 card_music
    • 检查 self.card_choose_num 是否等于4:
      • 如果等于4,表示用户已经选择了四种基础植物,此时:
        • worning_music.play()
        • 使用 messagebox.showinfo("错误", "你最多只能添加四种基础植物!")
        • 显示一个警告信息框,告知用户最多只能添加四种基础植物。
      • 如果不等于4,表示用户还可以添加更多基础植物,此时:
        • self.card_choose_photo_id[self.card_choose_num] = col+1+row*8
        • 将选中的植物卡片ID存储在 self.card_choose_photo_id 数组中,其中 col+1+row*8 是根据行和列计算出的卡片ID。
        • self.card_choose_num += 1
        • 增加已选择植物卡片的数量。
        • self.card_choose_frame()
        • 调用 self.card_choose_frame() 方法,可能用于更新界面或处理卡片选择逻辑。
  4. 绑定点击事件

    • button.bind('<Button-1>', lambda event, r=row, c=col: on_click(r, c))
    • 将 <Button-1> 事件(即鼠标左键点击)绑定到 on_click 函数上,其中 r=row 和 c=col 是传递给 on_click 函数的参数。

1.6 初始化基础植物卡片选择结果矩阵

 我们使用一个1*4的矩阵存储选择的基础植物卡片。当然了,还是老样子,空的部分我们用空白卡片填充

        # 基础植物卡片和选择框初始化self.empty_card = self.empty_card_load()
    def empty_card_load(self):"""空白卡片加载"""image = Image.open(emptycard_path)image = image.resize((78, 100), Image.Resampling.LANCZOS)photo = ImageTk.PhotoImage(image)return photo    

组件实现如下:

  self.card_choose_frame()
    def card_choose_frame(self):"""基础植物卡片选择框"""self.card_frame = tk.Frame(self,bd=0)self.card_frame.place(x=518,y=138)for col in range(4):if col < self.card_choose_num:self.card_choose_photo[col] = image_load(78,100,basal_card_path,self.card_choose_photo_id[col],".jpg")label = tk.Label(self.card_frame,image=self.card_choose_photo[col] ,bd=0)label.grid(row=0, column=col,sticky="NSEW")else:label = tk.Label(self.card_frame,image=self.empty_card,bd=0)label.grid(row=0, column=col,sticky="NSEW")    

这段代码定义了一个名为 card_choose_frame 的方法,用于创建和显示用户已选择的基础植物卡片选择框。 

  1. 创建卡片选择框架

    • self.card_frame = tk.Frame(self, bd=0)
    • 创建一个 tk.Frame 实例,作为卡片选择框的容器,并设置其父容器为 selfbd=0 表示没有边框。
    • self.card_frame.place(x=518, y=138)
    • 使用 place 方法将 self.card_frame 放置在父容器中的特定位置 (x=518, y=138)
  2. 填充卡片选择框

    • 使用 for 循环遍历列,从0到3(因为 col 范围是0到3,对应于最多4张卡片的选择)。
    • if col < self.card_choose_num:
      • 如果当前列号 col 小于 self.card_choose_num,表示用户已经选择了足够的卡片。
        • self.card_choose_photo[col] = image_load(78,100,basal_card_path,self.card_choose_photo_id[col],".jpg")
          • 调用 image_load 函数加载图片,将图片设置为卡片选择框中相应卡片的图片。参数包括图片的宽度和高度(78x100),卡片路径(basal_card_path),卡片ID(self.card_choose_photo_id[col])和文件扩展名(.jpg)。
        • label = tk.Label(self.card_frame, image=self.card_choose_photo[col], bd=0)
          • 创建一个 tk.Label 实例,用于显示卡片图片,并设置边框宽度为0。
        • label.grid(row=0, column=col, sticky="NSEW")
          • 使用 grid 布局管理器将标签放置在卡片选择框的相应位置,sticky="NSEW" 表示标签会粘在单元格的东、南、西、北边缘。
    • else:
      • 如果当前列号 col 大于或等于 self.card_choose_num,表示用户尚未选择足够的卡片。
        • label = tk.Label(self.card_frame, image=self.empty_card, bd=0)
          • 创建一个 tk.Label 实例,用于显示一个空卡片图片,self.empty_card 应该是一个空卡片的图片对象。
        • label.grid(row=0, column=col, sticky="NSEW")
          • 使用 grid 布局管理器将标签放置在卡片选择框的相应位置。

 1.7 杂交方式选择

self.method_choose_optionmenu()
    def method_choose_optionmenu(self):"""杂交方法选择"""def on_option_change(value):self.method_id = options.index(value) + 1options = [" 基础杂交方式 "," 使用强化药剂 ", " 单株辐射变异 "," 注射僵尸血清 "," 使用神奇魔法 "]selected_value = tk.StringVar()selected_value.set(" 杂交方式选择 ")option_menu = tk.OptionMenu(self, selected_value, *options, command=on_option_change,)option_menu.config(font=("华文新魏", 29, "bold"),bg="darkslategray",activebackground="gray",fg="limegreen", activeforeground="lime",borderwidth=0, highlightthickness=0)menu = option_menu['menu']menu.config(bg="darkslategray", fg="lime", font=("华文新魏", 25, "bold"))option_menu.place(x=530, y=386)

这段代码定义了一个名为 method_choose_optionmenu 的方法,用于创建一个下拉菜单(OptionMenu),让用户从预定义的杂交方法中选择一个选项。

  1. 内部函数定义

    • def on_option_change(value):
      • 定义了一个内部函数 on_option_change,该函数在选项改变时被调用。
      • self.method_id = options.index(value) + 1
      • 当选项改变时,将选择的选项的索引加1后赋值给 self.method_id。这通常用于将用户的选择转换为一个整数标识符,以便程序可以识别。
  2. 定义选项列表

    • options = [" 基础杂交方式 ", " 使用强化药剂 ", " 单株辐射变异 ", " 注射僵尸血清 ", " 使用神奇魔法 "]
    • 定义了一个名为 options 的列表,包含了下拉菜单中的所有选项。
  3. 创建 StringVar 对象

    • selected_value = tk.StringVar()
    • 创建了一个 tk.StringVar 对象,用于跟踪下拉菜单中当前选中的值。
    • selected_value.set(" 杂交方式选择 ")
    • 初始化 selected_value,将其设置为下拉菜单的默认选项。
  4. 创建 OptionMenu 控件

    • option_menu = tk.OptionMenu(self, selected_value, *options, command=on_option_change,)
    • 创建一个 tk.OptionMenu 控件,它允许用户从给定的选项中选择一个。
    • self 作为父容器传递给 OptionMenu,使下拉菜单能够正确地放置在GUI中。
    • *options 将 options 列表中的元素解包,作为选项传递给 OptionMenu
    • command=on_option_change 指定当用户选择一个选项时调用的函数。
  5. 配置 OptionMenu 控件

    • option_menu.config(...)
    • 使用 config 方法对 option_menu 进行配置,包括:
      • 字体样式和大小:font=("华文新魏", 29, "bold")
      • 背景和活动背景颜色:bg="darkslategray", activebackground="gray"
      • 文本颜色和活动文本颜色:fg="limegreen", activeforeground="lime"
      • 边框和突出显示宽度:borderwidth=0, highlightthickness=0
  6. 配置菜单的菜单项

    • menu = option_menu['menu']
    • 获取 option_menu 的菜单对象。
    • menu.config(bg="darkslategray", fg="lime", font=("华文新魏", 25, "bold"))
    • 对菜单项进行配置,设置背景、文本颜色和字体样式。
  7. 放置 OptionMenu 控件

    • option_menu.place(x=530, y=386)
    • 使用 place 方法将 option_menu 控件放置在父容器中的特定位置 (x=530, y=386)

1.8 杂交算法

这也是开始按钮的点击事件处理

    def on_breeding_method_select(self):"""杂交实验: 数据匹配1. 匹配杂交方法, 成功则:a. 匹配规则:规则1-4: 亲本植物是否为玩家选择的子集,是则杂交成功规则5: 产生一个随机数, 匹配随机植物b. 判断是否为新植物, 是则result=0,否则result=12. 失败则: result=23. 跳转至结果界面4. 修改杂交植物数据, 添加杂交记录"""def is_subset(list1, list2):# 子集判断return all(item in list2 for item in list1)def is_new(type):# 是否为新植物判断if type: return 0else: return 1sign = Falserandom_integer = random.randint(0, 6)num = 0for plant in self.master.hybridizationPlants:if plant.get("hybridization_method")==self.method_id: if self.method_id!=5:sign = is_subset(plant.get("parent_base_plant_ids"),self.card_choose_photo_id)if sign==True: breakelse:if num==random_integer:sign=Truebreakelse:num += 1if sign:success_music.play()self.result_plant_id = plant.get("id")self.result = is_new(plant.get("new_hybrid"))self.master.hybridizationPlants[self.result_plant_id-1]["new_hybrid"] = Falseelse:fail_music.play()self.result = 2self.result_plant_id = 0self.add_record()def add_record(self):# 添加杂交记录record = {  "id": len(self.master.recorditem)+1,"parent_base_plant_ids": self.card_choose_photo_id,"hybridization_method": self.method_id,"hybridization_plant_id": self.result_plant_id   }self.master.recorditem.append(record)

定义了一个名为 on_breeding_method_select 的方法,用于处理杂交实验中的数据匹配和结果处理。

  1. 定义内部函数

    • def is_subset(list1, list2):
      • 定义了一个内部函数 is_subset,用于判断一个列表是否是另一个列表的子集。
    • def is_new(type):
      • 定义了一个内部函数 is_new,用于判断一个植物是否为新植物。
  2. 初始化变量

    • sign = False
      • 初始化一个标志变量 sign,用于表示杂交是否成功。
    • random_integer = random.randint(0, 6)
      • 生成一个 0 到 6 之间的随机整数。
    • num = 0
      • 初始化一个计数器变量 num
  3. 遍历杂交植物

    • 通过遍历 self.master.hybridizationPlants 列表中的每个植物。
    • 对于每个植物,检查其杂交方法是否与当前选择的方法 self.method_id 匹配。
    • 如果方法不是 5,则使用 is_subset 函数检查亲本植物是否为玩家选择的子集。如果是,则设置标志变量 sign 为 True,并退出循环。
    • 如果方法是 5,则使用计数器 num 和随机整数 random_integer 来模拟随机匹配。如果计数器等于随机整数,则设置标志变量 sign 为 True,并退出循环。
  4. 处理杂交结果

    • 如果标志变量 sign 为 True,表示杂交成功。
    • 播放成功音乐。
    • 获取杂交成功的植物的 ID,并将其存储在 self.result_plant_id 变量中。
    • 使用 is_new 函数判断植物是否为新植物,并将结果存储在 self.result 变量中。
    • 将杂交成功的植物的 new_hybrid 属性设置为 False
    • 如果标志变量 sign 为 False,表示杂交失败。
    • 播放失败音乐。
    • 将 self.result 设置为 2,表示杂交失败。
    • 将 self.result_plant_id 设置为 0。
  5. 添加杂交记录

    • 调用 add_record 方法添加杂交记录。
    • 创建一个包含杂交记录信息的字典 record
    • 将记录的 ID 设置为当前记录数量加 1。
    • 将亲本植物的 ID 列表设置为玩家选择的照片 ID。
    • 将杂交方法设置为当前选择的方法。
    • 将杂交植物的 ID 设置为杂交成功的植物的 ID。
    • 将记录添加到 self.master.recorditem 列表中。

2. 实验结果

 其实共有三种结果:

  1. 杂交出来新植物
  2. 杂交出了已拥有植物,如上图
  3. 杂交失败

class ResultScreen(tk.Frame):"""杂交结果界面"""def __init__(self, parent):super().__init__(parent)self.breeding_background = create_background(self,result_background_path)self.back_button = create_button(self,dark_image_path=result_back1_path,light_image_path=result_back2_path,width=85,height=25,locate_x=24,locate_y=567,command=self.on_back_button_click)self.result_plant = Noneself.result_text = [None, None, None]self.result_text_load()self.pack()def result_text_load(self):"""加载结果的三种情况"""for col in range(3):self.result_text[col] = image_load(300,90,result_path,col+1,".png")def on_back_button_click(self):"""返回植物杂交界面"""self.master.children['experiment_screen'].on_clear_button_click()self.master.switch_to_screen('experiment_screen')def result_show(self,result,result_plants_id):"""result: 0. 新植物1. 已经获得2. 杂交失败"""self.label1 = tk.Label(self,image=self.result_text[result],bd=0)self.label1.place(x=290,y=362)if result_plants_id!=0:self.result_plant = image_load(114,156,hybrid_card_path,result_plants_id,".jpg")else:image = Image.open(emptyresult_path)image = image.resize((114, 156), Image.Resampling.LANCZOS)self.result_plant = ImageTk.PhotoImage(image)self.label2 = tk.Label(self,image=self.result_plant,bd=0)self.label2.place(x=382,y=123)

这段代码定义了一个名为 ResultScreen 的类,用于创建植物杂交结果的界面。这个界面包含了用于显示杂交结果的图像、返回按钮以及用于加载和显示结果文本的功能。 

初始化方法 __init__

  • 初始化背景:通过调用 create_background 函数创建一个背景图像,并将其设置为 self.breeding_background
  • 创建返回按钮:使用 create_button 函数创建一个按钮,该按钮在用户点击时调用 on_back_button_click 方法返回到植物杂交界面。
  • 初始化结果变量:设置 self.result_plant 为 None,用于存储显示的杂交结果植物图像。同时,初始化 self.result_text 为一个包含三个 None 的列表,用于存储结果文本的图像。
  • 加载结果文本:调用 result_text_load 方法来加载结果的文本图像。
  • 布局:使用 pack 方法将界面组件添加到父窗口中。

result_text_load 方法

  • 加载结果文本:遍历列表的三个元素,为每种结果情况加载相应的文本图像,并存储在 self.result_text 列表中。

on_back_button_click 方法

  • 返回到植物杂交界面:通过调用 master.children['experiment_screen'].on_clear_button_click() 清空实验屏幕的组件,并使用 master.switch_to_screen('experiment_screen') 切换回植物杂交界面。

result_show 方法

  • 显示结果:根据 result 参数的值显示不同的结果图像。如果结果为 0(表示新植物),则显示新植物的图像;如果结果为 1(表示已获得),则显示已获得植物的图像;如果结果为 2(表示杂交失败),则显示失败的图像。
  • 显示杂交结果植物:根据 result_plants_id 参数的值加载并显示杂交结果植物的图像。如果 result_plants_id 为 0,表示没有结果植物,因此使用空图像。

3. 历史记录

历史记录这个模块略微复杂,因为涉及一个切页操作,并且每一条历史记录数据都是单独呈现的

3.1 类定义与初始化 

class RecordScreen(tk.Frame):"""杂交记录界面1. 每页3条记录2. 最多3页记录"""def __init__(self, parent):super().__init__(parent)self.breeding_background = create_background(self,record_background_path)self.close_button = close_button(self,close1_1_path,close1_2_path)self.back_button = back_button(self,back1_1_path,back1_2_path)self.ahead_buttton = create_button(self,dark_image_path=ahead2_1_path,light_image_path=ahead2_2_path,width=110,height=27,locate_x=330,locate_y=564,command=self.on_ahead_button_click)self.ahead_buttton = create_button(self,dark_image_path=next2_1_path,light_image_path=next2_2_path,width=110,height=27,locate_x=450,locate_y=564,command=self.on_next_button_click)self.page = 0self.record_num = 0self.empty_card = self.empty_card_load()self.empty_method = self.empty_method_load()self.all_record(page=0)self.pack()def empty_card_load(self):# 加载空白卡片image = Image.open(emptycard_path)image = image.resize((78, 100), Image.Resampling.LANCZOS)photo = ImageTk.PhotoImage(image)return photo  def empty_method_load(self):# 加载空白方法image = Image.open(emptymethod_path)image = image.resize((175, 100), Image.Resampling.LANCZOS)photo = ImageTk.PhotoImage(image)return photo        def on_ahead_button_click(self):if self.page!=0:self.page -= 1self.all_record(self.page)self.pack()def on_next_button_click(self):if self.page!=2 and (self.record_num-3*(self.page+1))>0:self.page += 1self.all_record(self.page)self.pack()

 这段代码定义了一个名为 RecordScreen 的类,用于创建植物杂交记录的界面。这个界面允许用户浏览最多3页的记录,每页显示3条记录。

初始化方法 __init__

  • 初始化背景:通过调用 create_background 函数创建一个背景图像,并将其设置为 self.breeding_background
  • 创建按钮:创建关闭按钮、返回按钮以及用于跳转到上一页和下一页的按钮。这些按钮分别调用 close_buttonback_buttonon_ahead_button_click 和 on_next_button_click 方法。
  • 初始化页面和记录数:设置 self.page 为 0,表示当前显示第一页记录;设置 self.record_num 为 0,表示记录总数。
  • 加载空白卡片和空白方法:通过调用 empty_card_load 和 empty_method_load 方法加载空白卡片和空白方法的图像,并存储在 self.empty_card 和 self.empty_method 中。
  • 加载所有记录:调用 all_record 方法初始化显示的记录,并使用 pack 方法将界面组件添加到父窗口中。

empty_card_load 方法

  • 加载空白卡片:从指定路径加载空白卡片的图像,调整尺寸,并转换为 ImageTk.PhotoImage 格式以便在界面上显示。

empty_method_load 方法

  • 加载空白方法:与 empty_card_load 类似,从指定路径加载空白方法的图像,调整尺寸,并转换为 ImageTk.PhotoImage 格式。

on_ahead_button_click 方法

  • 跳转到上一页:如果当前页不是第一页,减小 self.page 的值,调用 all_record 方法重新加载记录,并使用 pack 方法重新布局界面。

on_next_button_click 方法

  • 跳转到下一页:如果当前页不是最后一页,并且还有更多记录可以显示,增加 self.page 的值,调用 all_record 方法重新加载记录,并使用 pack 方法重新布局界面。

3.2 历史记录数据加载 

    def data_load(self):"""加载杂交记录数据"""records = self.master.recorditemrecords = records[::-1]self.basal_plants_card = [[None for _ in range(4)] for _ in range(9)]self.hybrid_plants_card = [None for _ in range(9)] self.method = [None for _ in range(9)] self.record_num = 0for index, item in enumerate(records):basal_plant_card = item.get("parent_base_plant_ids")for col in range(len(basal_plant_card)):if basal_plant_card[col]!=0:self.basal_plants_card[index][col] = image_load(78,100,basal_card_path,basal_plant_card[col],".jpg")if item.get("hybridization_plant_id")!=0:self.hybrid_plants_card[index] = image_load(78,100,hybrid_card_path,item.get("hybridization_plant_id"),".jpg")self.method[index] = image_load(175,100,method_path,item.get("hybridization_method"),".png")self.record_num += 1if index==8: break

data_load 方法是 RecordScreen 类的一个方法,用于加载杂交记录数据。以下是该方法的详细解释:

方法目的

  • 加载保存在 self.master.recorditem 中的杂交记录数据,并将这些数据用于界面显示。

方法步骤

  1. 反转记录列表:将 self.master.recorditem 中的记录列表反转,这是因为希望最新的记录显示在最前面。

  2. 初始化卡片和方法列表

    • self.basal_plants_card:创建一个9行4列的二维列表,用于存储基础植物卡片的图像,每行对应一条记录,每列对应一个基础植物。
    • self.hybrid_plants_card:创建一个9元素的列表,用于存储杂交植物卡片的图像,每个元素对应一条记录。
    • self.method:创建一个9元素的列表,用于存储杂交方法的图像,每个元素对应一条记录。
  3. 初始化记录数:将 self.record_num 设置为0,用于记录已加载的记录数量。

  4. 遍历记录:遍历反转后的记录列表 records,对每条记录执行以下操作:

    • 加载基础植物卡片:从记录中获取基础植物ID列表 basal_plant_card,然后遍历这个列表,对于每个非零ID,调用 image_load 函数加载对应的图像,并将其存储在 self.basal_plants_card 对应的位置。
    • 加载杂交植物卡片:如果记录中的杂交植物ID不为零,调用 image_load 函数加载对应的图像,并将其存储在 self.hybrid_plants_card 对应的位置。
    • 加载杂交方法:调用 image_load 函数加载对应的杂交方法图像,并将其存储在 self.method 对应的位置。
    • 更新记录数:每次循环结束时,增加 self.record_num 的值。
  5. 终止条件:如果已经遍历了9条记录,则终止循环。

3.3 记录显示

    def one_item(self,id):"""展示一条数据: 亲本植物+杂交方法+杂交植物"""line = id% 3 #  亲本植物self.card_frame = tk.Frame(self,bd=0)self.card_frame.place(x=156,y=108+line*155)for col in range(4):if self.basal_plants_card[id][col]!=None:label = tk.Label(self.card_frame,image=self.basal_plants_card[id][col] ,bd=0)label.grid(row=0, column=col,sticky="NSEW")else:label = tk.Label(self.card_frame,image=self.empty_card,bd=0)label.grid(row=0, column=col,sticky="NSEW")         # 杂交方法if self.method[id]!=None:label2 = tk.Label(self,image=self.method[id],bd=0)else:label2 = tk.Label(self,image=self.empty_method,bd=0)label2.place(x=475,y=line*155+109)# 杂交植物if self.hybrid_plants_card[id]!=None:label3 = tk.Label(self,image=self.hybrid_plants_card[id],bd=0)else:label3 = tk.Label(self,image=self.empty_card,bd=0)label3.place(x=654,y=line*155+109)def all_record(self,page=0):self.data_load()self.one_item(0+page*3)self.one_item(1+page*3)self.one_item(2+page*3)

one_item 和 all_record 是两个用于展示数据的方法,它们可能是 tkinter GUI 应用程序中的一部分,用于在一个图形用户界面中展示杂交记录的详细信息。

one_item 方法

这个方法用于展示一条具体的记录,它包含以下步骤:

  1. 计算行位置:通过 id % 3 计算出记录应该显示的行位置。

  2. 创建并放置卡片框架:创建一个 tk.Frame 对象 self.card_frame,然后根据行位置将其放置在界面上。

  3. 展示亲本植物卡片

    • 遍历 self.basal_plants_card[id] 列表,对于每个非空的图像,创建一个 tk.Label 并将其放置在框架中。
    • 如果某个位置是空的(即 None),则显示一个空卡片图像。
  4. 展示杂交方法

    • 如果 self.method[id] 不为空,则创建一个 tk.Label 来展示对应的图像。
    • 如果为空,则展示一个空的方法图像。
  5. 展示杂交植物卡片

    • 如果 self.hybrid_plants_card[id] 不为空,则创建一个 tk.Label 来展示对应的图像。
    • 如果为空,则展示一个空卡片图像。

all_record 方法

这个方法用于展示所有记录,它包含以下步骤:

  1. 加载数据:调用 self.data_load() 方法来加载杂交记录数据。

  2. 展示记录:根据给定的页面 page 参数,调用 self.one_item 方法来展示每条记录。每页显示3条记录,通过 page*3 计算出当前页的第一条记录的索引。

4. 总结

到这里整个项目的全部内容就结束了,今天我们实现了杂交实验、实验结果、杂交记录三个界面。杂交实验重点在于植物卡片的选择、杂交方法的选择,以及匹配算法;杂交记录则是在数据加载和展示部分略微复杂一点。

下期预告:我将对博客进行汇总,介绍我使用到的工具,以及将代码和数据文件放在GitHub仓库。

感谢大家支持!

这篇关于10天速通Tkinter库——Day8:《植物杂交实验室》杂交实验及历史记录界面的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1113125

相关文章

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STL经典案例(四)——实验室预约综合管理系统(项目涉及知识点很全面,内容有点多,耐心看完会有收获的!)

项目干货满满,内容有点过多,看起来可能会有点卡。系统提示读完超过俩小时,建议分多篇发布,我觉得分篇就不完整了,失去了这个项目的灵魂 一、需求分析 高校实验室预约管理系统包括三种不同身份:管理员、实验室教师、学生 管理员:给学生和实验室教师创建账号并分发 实验室教师:审核学生的预约申请 学生:申请使用实验室 高校实验室包括:超景深实验室(可容纳10人)、大数据实验室(可容纳20人)、物联网实验

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

一款支持同一个屏幕界面同时播放多个视频的视频播放软件

GridPlayer 是一款基于 VLC 的免费开源跨平台多视频同步播放工具,支持在一块屏幕上同时播放多个视频。其主要功能包括: 多视频播放:用户可以在一个窗口中同时播放任意数量的视频,数量仅受硬件性能限制。支持多种格式和流媒体:GridPlayer 支持所有由 VLC 支持的视频格式以及流媒体 URL(如 m3u8 链接)。自定义网格布局:用户可以配置播放器的网格布局,以适应不同的观看需求。硬

全英文地图/天地图和谷歌瓦片地图杂交/设备分布和轨迹回放/无需翻墙离线使用

一、前言说明 随着风云局势的剧烈变化,对我们搞软件开发的人员来说,影响也是越发明显,比如之前对美对欧的软件居多,现在慢慢的变成了对大鹅和中东以及非洲的居多,这两年明显问有没有俄语或者阿拉伯语的输入法的增多,这要是放在2019年以前,一年也遇不到一个人问这种需求场景的。 地图应用这块也是,之前的应用主要在国内,现在慢慢的多了一些外国的应用场景,这就遇到一个大问题,我们平时主要开发用的都是国内的地

Python知识点:如何使用Python开发桌面应用(Tkinter、PyQt)

Python 提供了多个库来开发桌面应用程序,其中最常见的两个是 Tkinter 和 PyQt。这两者各有优点,选择取决于你的需求。以下我会介绍如何使用 Tkinter 和 PyQt 开发简单的桌面应用程序。 1. 使用 Tkinter 开发桌面应用 Tkinter 是 Python 的标准库,它非常轻量级且跨平台。它适合开发简单的桌面应用,入门较容易。 安装 Tkinter Tkinte

centOS7.0设置默认进入字符界面

刚装的,带有x window桌面,每次都是进的桌面,想改成自动进命令行的。记得以前是修改 /etc/inittab 但是这个版本inittab里的内容不一样了没有id:x:initdefault这一行而且我手动加上也不管用,这个centos 7下 /etc/inittab 的内容 Targets systemd uses targets which serve a simil

Appium--界面元素选择

在操作界面元素前,我们需要进行手机与电脑的连接,这里介绍一个adb无线连接的方法: Adb无线连接功能 无线连接步骤(确保手机和电脑处于同一局域网) 1先以USB有线连接方式连接到计算机 2激活手机adb的无线服务: 命令行输入adb tcpip 5555(5555是端口号) 3计算机以无线方式连接到手机: 命令行输入adb connect 配置信息 desired_caps:这些键值对告诉ap

基于JSP的实验室管理系统

你好呀,我是计算机学姐码农小野!如果有相关需求,可以私信联系我。 开发语言:Java 数据库:MySQL 技术:JSP技术 + Spring Boot框架 工具:IDEA/Eclipse、Navicat、Tomcat 系统展示 首页 用户个人中心 实验室管理 设备报备管理 摘要 随着社会的发展和科学技术的进步,互联网技术越来越受欢迎。网络计算机

61.以太网数据回环实验(4)以太网数据收发器发送模块

(1)状态转移图: (2)IP数据包格式: (3)UDP数据包格式: (4)以太网发送模块代码: module udp_tx(input wire gmii_txc ,input wire reset_n ,input wire tx_start_en , //以太网开始发送信