You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Tkinter中更新下拉菜单结果并传递给函数?

解决Tkinter下拉菜单选中值无法传递给函数的问题

核心问题分析

  • 原代码在页面加载时就获取OptionMenu的文本值,而非用户选择后的实时值,且OptionMenu的text属性并非选中项内容,应该通过绑定的StringVar获取。
  • 使用partial传参时传递的是初始固定值,没有在按钮点击时动态获取最新选中值。
  • Craft函数中错误地将读取的CSV数据覆盖为空列表,导致配方检查逻辑失效。
  • 子窗口的标题和尺寸设置错误地作用在了主窗口上。

修改步骤

  1. 实时获取选中值:在按钮点击时,通过StringVar的get()方法获取当前选中的配料值,而非页面加载时的初始值。
  2. 调整点击逻辑:用自定义函数替代直接传参的partial,确保点击时动态拉取最新选中值。
  3. 修复配方读取逻辑:移除清空recipe列表的代码,保留CSV读取的有效数据。
  4. 修正窗口属性:将子窗口的标题和尺寸设置正确作用在子窗口对象上。

修改后的完整代码

from tkinter import *
import csv
from functools import partial

menu = Tk()
menu.title('Level 3 Crafting')
menu.geometry("1080x1600")

ingredient1 = ["Time", "Love", "Truth", "Cruelty", "Mortality", "Earth", "Air", "Water", "Fire", "Magic"]
ingredientAlch = ["Aqua Vitae", "Antimony", "Cinnebar", "Vitriol", "Mercury", "Gold", "Oxygen", "Vinnegar", "Sulfur", "Platinum"]
ingredient3 = ["Embroidery", "Needle", "Fabric", "Beiline", "Dye", "Metal Sheet", "Sack", "Wool", "Fiber Ash", "String", "Carved Obelisk", "Attraction Circle", "Binding Rune",
               "Blood Mark", "Death Knell", "Dirt", "Extinguishing Breath", "Etched Droplet", "Line of Flame", "Strand of Aether", "Crystal", "Opal", "Lapis Lazuli", "Diamond", "Glass Bead", "Chain",
               "Twine", "Pearl", "Amber", "Waxed String", "Aqua Vitae", "Antimony", "Cinnebar", "Vitriol", "Mercury", "Gold", "Oxygen", "Vinnegar", "Sulfur", "Platinum", "Bread", "Stew",
               "Clarified honey", "Incredibly Spicy Pepper", "Fried Dough", "Meat", "Mousse", "Rice", "Potato", "Dumpling", "Rabbit's Foot", "Strip of Darkness", "Lightning in a Bottle",
               "Pheonix Feather", "Spectral Antler"]


def CSVReader(csvFileName):
    rawdata = []
    with open(csvFileName, "r") as file:
        reader = csv.reader(file)
        for row in reader:
            rawdata.append(row)
    return rawdata

def Craft(i1, i2, i3, mode):
    wCraft = Toplevel()
    wCraft.title('Crafted')
    wCraft.geometry("400x600")
    
    fileName = mode + ".csv"
    recipe = CSVReader(fileName)
    thing = []
    track1 = []
    track2 = []
    track3 = []

    print(i1, i2, i3)
    
    # 检查配料对应的配方
    for row in recipe:
        if len(row) >=4:
            piece = 0
            if row[0] == i1:
                track1.append(f"{i1} is an ingredient in {row[3]}")
                piece +=1
            if row[1] == i2:
                track2.append(f"{i2} is an ingredient in {row[3]}")
                piece +=1
            if row[2] == i3:
                track3.append(f"{i3} is an ingredient in {row[3]}")
                piece +=1
            if piece ==3:
                thing.append(row[3])
        
    if not thing:
        thing.append("You Made Nothing")
        thing.append("Try again with this information:")
        
    # 显示结果
    Label(wCraft, text=thing[0]).grid(row=2, column=1, pady=5)
    if len(thing)>=2:
        Label(wCraft, text=thing[1]).grid(row=3, column=1, pady=5)

    # 显示各配料对应的配方提示
    current_row = 4
    for text in track1:
        Label(wCraft, text=text).grid(row=current_row, column=1, sticky="w", pady=2)
        current_row +=1
    for text in track2:
        Label(wCraft, text=text).grid(row=current_row, column=1, sticky="w", pady=2)
        current_row +=1
    for text in track3:
        Label(wCraft, text=text).grid(row=current_row, column=1, sticky="w", pady=2)
        current_row +=1

def alchCraft():
    alch = Toplevel()
    alch.title("Level 3 Alchemy")
    alch.geometry("1080x1600")

    # 定义绑定下拉菜单的变量
    Bit1 = StringVar(value="Ingredient 1")
    alchI1 = OptionMenu(alch, Bit1, *ingredient1)
    Bit2 = StringVar(value="Ingredient 2")
    alchI2 = OptionMenu(alch, Bit2, *ingredientAlch)
    Bit3 = StringVar(value="Ingredient 3")
    alchI3 = OptionMenu(alch, Bit3, *ingredient3)

    alchI1.grid(row=0, column=0, padx=10)
    alchI2.grid(row=0, column=1, padx=10)
    alchI3.grid(row=0, column=2, padx=10)

    # 按钮点击时实时获取选中值
    def on_craft_click():
        i1 = Bit1.get()
        i2 = Bit2.get()
        i3 = Bit3.get()
        Craft(i1, i2, i3, "Alchemy")
    
    butCraft = Button(alch, text="Craft", command=on_craft_click)
    butCraft.grid(row=1, column=1, pady=20)

butAlch = Button(menu, text="Alchemy", command=alchCraft)
butAlch.grid(row=0, column=0)

menu.mainloop()

额外优化说明

  • 使用with open语句管理文件,自动关闭文件避免资源泄漏。
  • 调整结果标签布局,增加间距和左对齐,提升可读性。
  • 移除子窗口的mainloop()调用,主窗口的事件循环会处理所有子窗口。

内容的提问来源于stack exchange,提问作者Saminthea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 03:44:53