使用 combobox 在 tkinter gui 中生成入口小部件,然后获取输入的值以供稍后在脚本中使用

Generate entry widgets in tkinter gui using combobox, then get the values entered for use later in script

提问人:PyGuy2000 提问时间:11/16/2023 更新时间:11/17/2023 访问量:43

问:

我有一个python脚本,它使用tkinter gui来生成用于用户值插入的输入框。生成的输入框数是从组合框(1 或 2)中选择的,该组合框允许用户输入适当数量的项目的数据。然后,这些值应填充字典,以便以后可以调用它们以用作变量。我能够生成框,但是当我输入数据并提交时,值似乎没有填充字典。

我试过这个:

import os
import re
import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.title('Rack Position & Injection Volume')
root.geometry("700x200")

numbers = [1, 2]
combo = ttk.Combobox(root, values=numbers)
combo.grid(row=0, column=1)
combo.set(numbers[0])
combo_label = tk.Label(root, text="Select number of plates for this sequence:").grid(column=0, row=0)
combo['state'] = 'normal'
global selected_number
slected_number= int(combo.get())


def generate_entry_boxes():
    global selected_number, entry1_boxes, entry2_boxes, entry1_labels, entry1_values, entry2_values, entry2_labels, buttons
    entry1_boxes = []
    entry1_values = {}
    entry2_boxes = []
    entry2_values = {}
    entry_labels = []
    entry2_labels = []
    buttons = []
    for entry in entry1_boxes:
        entry.destroy()
        entry1_boxes.clear()
    for entry2 in entry2_boxes:
        entry2.destroy()
        entry2_boxes.clear()
    for label in entry_labels:
        label.destroy()
        entry_labels.clear()
    for label2 in entry2_labels:
        label2.destroy()
        entry2_labels.clear()
    for button in buttons:
        button.destroy()
        buttons.clear()

    for i in range(slected_number):
        entry1_values[i] = tk.StringVar()
        entry1 = ttk.Entry(root, textvariable=entry1_values[i])
        entry1.grid(row=i+1, column=1)
        entry1_boxes.append(entry1)
        entry2_values[i] = tk.StringVar()
        entry2 = ttk.Entry(root, textvariable=entry2_values[i])
        entry2.grid(row=i+1, column=3)
        entry2_boxes.append(entry2)
        label = ttk.Label(root, text="Position of plate " + str(i+1) + ":")
        label.grid(row=i+1, column=0)
        entry_labels.append(label)
        label2 = ttk.Label(root, text="Injection Volume(uL):")
        label2.grid(row=i+1, column=2)
        entry2_labels.append(label2)
        button = tk.Button(root, text="Submit", command=get_entries)
        button.grid(row=selected_number + 1, column=1)
        buttons.append(button)


def get_entries():
    for i, entry in enumerate(entry1_boxes):
        entry1_values[i] = entry.get()
    for i, entry in enumerate(entry2_boxes):
        entry2_values[i] = entry.get()
    entry_plate1 = entry1_values.get('0', 'Key not found')
    entry_plate2 = entry1_values.get('1', 'Key not found')
    entry_vol1 = entry2_values.get('0', 'Key not found')
    entry_vol2 = entry2_values.get('1', 'Key not found')
    condition_mask = df['Vial Position'] == 1
    second_occurrence_index = df[condition_mask].index[1]
    after_mask = df.index >= second_occurrence_index
    df.loc[~after_mask, 'Rack Position'] = entry_plate1
    df.loc[after_mask, 'Rack Position'] = entry_plate2
    df['Plate Position'] = df['Rack Position']
    df.loc[~after_mask, 'Injection Volume'] = entry_vol1
    df.loc[after_mask, 'Injection Volume'] = entry_vol2


combo.bind("<<ComboboxSelected>>", lambda event: generate_entry_boxes())
root.mainloop()

并期望从生成的输入框中获取 entry_plate1、entry_plate2、entry_vol1 和 entry_vol2 的值,但我的数据显示“找不到密钥”

蟒蛇 tkinter

评论

0赞 acw1668 11/16/2023
有错别字:还是?也是未定义的。如果不需要重现该问题,请删除相关代码,使其成为可重现的最小示例。同时发布完整的回溯。selected_numberslected_numberdf
0赞 PyGuy2000 11/17/2023
对不起,我是新手。我将调整代码以使其可重现
0赞 Derek 11/17/2023
运行代码会生成“NameError: name 'selected_number' is not defined”错误。尝试更改为global selected_numberselected_number = 1
0赞 toyota Supra 11/20/2023
第 74 行,在 get_entries condition_mask = df['Vial Position'] == 1 ^^ NameError: name 'df' is not defined
0赞 D.L 11/24/2023
使用和方法来代替访问函数中的 tkinter 变量是一种很好的做法......get()set()global

答:

0赞 acw1668 11/17/2023 #1

代码中存在问题:

  • 错别字:应该是slected_numberselected_number
  • 需要在外部创建和初始化这些列表和字典generate_entry_boxes()
  • 需要在 for 循环之后清除这些列表和字典
  • 只需创建一个“提交”按钮
  • 需要打电话到里面selected_number = int(combo.get())generate_entry_boxes()
  • 调用内部的键时需要使用整数而不是字符串xxxxx_values.get(...)get_entries()

以下是修复问题所需的更改:

...
# below lines are not necessary
#global selected_number
#slected_number= int(combo.get())

# initialize the lists and dictionaries
entry1_boxes = []
entry1_values = {}
entry2_boxes = []
entry2_values = {}
entry_labels = []
entry2_labels = []
buttons = []

def generate_entry_boxes():
    global selected_number, entry1_boxes, entry2_boxes, entry1_labels, entry1_values, entry2_values, entry2_labels, buttons
    for entry in entry1_boxes:
        entry.destroy()
    # clear list after the for loop
    entry1_boxes.clear()
    for entry2 in entry2_boxes:
        entry2.destroy()
    entry2_boxes.clear()
    for label in entry_labels:
        label.destroy()
    entry_labels.clear()
    for label2 in entry2_labels:
        label2.destroy()
    entry2_labels.clear()
    for button in buttons:
        button.destroy()
    buttons.clear()

    # get the selected number from the combobox
    selected_number = int(combo.get())
    # fix typo "slected_number" -> "selected_number"
    for i in range(selected_number):
        ...
    # need to create only one submit button after the for loop
    button = tk.Button(root, text="Submit", command=get_entries)
    button.grid(row=selected_number + 1, column=1)
    buttons.append(button)

def get_entries():
    ...
    # use integers as keys
    entry_plate1 = entry1_values.get(0, 'Key not found')
    entry_plate2 = entry1_values.get(1, 'Key not found')
    entry_vol1 = entry2_values.get(0, 'Key not found')
    entry_vol2 = entry2_values.get(1, 'Key not found')
    ...