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

Tkinter实现0/1背包程序报错:knapSack()缺失3个必填参数

解决Tkinter 0/1背包程序的回调错误及运行问题

错误原因分析

  • 点击计算按钮时直接调用knapSack(),但该函数需要W(背包容量)、wt(物品重量列表)、val(物品价值列表)三个参数,Tkinter按钮回调默认不会传递参数,因此触发TypeError。
  • 原代码中on_submit函数存在重复创建控件的问题(循环里重复创建标题、容量选择控件、计算按钮),且没有保存输入控件的引用,无法获取用户输入的重量、价值和容量值。

修复步骤及完整代码

1. 保存输入控件引用

创建全局列表存储重量和价值的输入框,保存容量选择框的引用,方便后续获取输入值。

2. 调整回调逻辑

将计算按钮的回调改为一个中间函数,在该函数中获取用户输入的数值,转换为整数后再调用knapSack。

3. 优化控件创建逻辑

避免循环中重复创建标题、标签等静态控件,仅循环创建物品重量和价值的输入框。

修改后的完整代码:

import tkinter as tk

window = tk.Tk()
window.title("0/1 Knapsack")

canvas = tk.Canvas(window, height=1000, width=1000, bg="#ADD8E6")
canvas.pack()

frame = tk.Frame(window, bg="white")
frame.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1)

# 全局变量存储输入控件
weight_entries = []
value_entries = []
capacity_spinbox = None

def on_submit():
    global weight_entries, value_entries, capacity_spinbox
    # 清空之前的输入框(如果有的话)
    for entry in weight_entries + value_entries:
        entry.destroy()
    weight_entries.clear()
    value_entries.clear()
    
    num_entries = int(num_entries_entry.get())
    
    # 创建静态标签,只创建一次
    Title_label = tk.Label(frame, text="Items information", font=("Arial", 18), bg="white")
    Title_label.grid(row=5, column=1)
    
    entry_label = tk.Label(frame, text=" Weight of items : ", bg="white")
    entry_label.grid(row=6, column=0)
    
    entry2_label = tk.Label(frame, text=" Value of each items", bg="white")
    entry2_label.grid(row=6, column=1)
    
    capacity_label = tk.Label(frame, text=" Please select the capacity of your bag :", bg="white")
    capacity_label.grid(row=6, column=2)
    
    capacity_spinbox = tk.Spinbox(frame, from_=1, to=100)
    capacity_spinbox.grid(row=7, column=2)
    
    # 循环创建物品重量和价值输入框
    for i in range(num_entries):
        weight_entry = tk.Entry(frame)
        weight_entry.grid(row=7+i, column=0)
        weight_entries.append(weight_entry)
        
        value_entry = tk.Entry(frame)
        value_entry.grid(row=7+i, column=1)
        value_entries.append(value_entry)
    
    # 创建计算按钮,回调为中间函数
    calculate_button = tk.Button(frame, text="Calculate", command=calculate_result)
    calculate_button.grid(row=7+num_entries, column=3)

def calculate_result():
    global weight_entries, value_entries, capacity_spinbox
    # 获取并转换输入值
    try:
        weights = [int(entry.get()) for entry in weight_entries]
        values = [int(entry.get()) for entry in value_entries]
        capacity = int(capacity_spinbox.get())
    except ValueError:
        # 处理输入非数字的情况
        result_label = tk.Label(frame, text="Error: 请输入整数数值", fg="red", bg="white")
        result_label.grid(row=14, column=0)
        return
    
    # 调用背包算法
    result = knapSack(capacity, weights, values)
    # 显示结果
    result_label = tk.Label(frame, text=f"最大价值: {result}", bg="white")
    result_label.grid(row=14, column=0)

def print_value_table(table):
    print("Value Table:")
    for row in table:
        print(row)
        
def print_keep_table(table):
    print("Keep Table:")
    for row in table:
        print(row)
        
def knapSack(W, wt, val): 
    n = len(val)
    value_table = [[0 for x in range(W + 1)] for x in range(n + 1)]
    keep_table = [[0 for x in range(W+1)] for x in range(n+1)]
    for i in range(n + 1): 
        for j in range(W + 1): 
            if i == 0 or j == 0: 
                value_table[i][j] = 0
                keep_table[i][j] = 0
            elif wt[i-1] <= j: 
                if(val[i-1] + value_table[i-1][j-wt[i-1]]) > value_table[i-1][j]:
                    value_table[i][j] = val[i-1] + value_table[i-1][j-wt[i-1]]
                    keep_table[i][j] = 1
                else:
                    value_table[i][j] = value_table[i-1][j]
                    keep_table[i][j] = 0
            else: 
                value_table[i][j] = value_table[i-1][j]
                keep_table[i][j] = 0
    print_value_table(value_table)
    print_keep_table(keep_table)
    return value_table[n][W]        

# 初始界面控件
num_entries_label = tk.Label(frame, text="Enter the number of items:", bg="white")
num_entries_label.grid(row=1, column=1)

num_entries_entry = tk.Entry(frame)
num_entries_entry.grid(row=2, column=1)

next_button = tk.Button(frame, text="Next", command=on_submit)
next_button.grid(row=3, column=1)

title_label = tk.Label(frame, text="Hi! Please follow the instructions!", font=("Arial", 18), bg="white")
title_label.grid(row=0, column=1)

window.mainloop()

关键修复说明

  • 全局变量存储控件:使用weight_entries、value_entries列表保存每个物品的重量和价值输入框,capacity_spinbox保存容量选择框,确保在计算时能获取到用户输入。
  • 中间回调函数:新增calculate_result函数作为按钮回调,该函数负责获取输入值、转换类型、处理输入错误,再调用knapSack计算结果并显示。
  • 优化控件创建:将静态标签(如物品信息标题、重量/价值标签)移到循环外,避免重复创建;每次点击Next时先清空之前的输入框,防止界面混乱。
  • 错误处理:添加try-except捕获输入非整数的情况,给用户明确的错误提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:45:35