python 未在使用Tkinter的嵌套窗口中定义变量

ars1skjm  于 2023-05-05  发布在  Python
关注(0)|答案(3)|浏览(141)

我正在用Python和Tkinter制作一个GUI(Python版本3.11.3和Spyder)。
GUI用于控制某种类型的机器(像日志文件,但更简单)。在根窗口(ventana principal)中,当我单击“No aceptable”(boton_flujo_2)时,另一个窗口将打开Toplevel(称为“Ventana 1”)。在该窗口中,我想,如果“没有necesario 2”被选中,该窗口中的按钮应被禁用。我在“Ventana principal”中使用了相同的逻辑,它起作用了,但是当我想在“Ventana 1”中使用时,我有下一个错误:
"NameError: name 'mensual_check_top1' is not defined"
我的代码是下一个:

import tkinter as tk
from tkinter import ttk 

#Para deshabilitar widgets segun ciertas condiciones    
def disable_widgets():
    # disable dropdown menu si Valve Status "0 (cero)" esta checkeado
    if cero_check.get() == 1:
        dropdown.config(state='disabled')
    else:
        dropdown.config(state='readonly')

  # disable flujo box si "5lpm" esta checkeado
    if flow_check.instate(['selected']):
        flow_entry.config(state='disabled')
    else:
        flow_entry.config(state='normal')
        
  # disable boton_flujo widget en CONTROL MENSUAL si "no necesario" esta checkeado
    if control_mensual_check.instate(['selected']):
        boton_flujo_1.config(state='disabled')
        boton_flujo_2.config(state='disabled')
        #boton_flujo_3.config(state='disabled')
        #boton_flujo_4.config(stapte='disabled')
    else:
        boton_flujo_1.config(state='normal')
        boton_flujo_2.config(state='normal')
       # boton_flujo_3.config(state='normal')
       # boton_flujo_4.config(state='normal')
         
  # disable boton_flujo widget en Ventana 1 si "No necesario 2" esta checked
    if mensual_check_top1.instate(['selected']):
        boton_flujo_3.config(state='disabled')
        boton_flujo_4.config(state='disabled')
    else:
        boton_flujo_3.config(state='normal')
        boton_flujo_4.config(state='normal')
        
#Para que Status solo admita numeros
def validate_numeric_input(new_value):
    return new_value.isnumeric()

#Ventana 1
def realizar_calibracion():
    
 
    ventana1 = tk.Toplevel(root)
    ventana1.geometry("300x100")
    ventana1.title("Ventana 1")

    verif_flujo_mensual = ttk.Label(ventana1, text="Verificacion de flujo")
    verif_flujo_mensual.grid(row=0, column=1)
    
    mensual_check_top1 = ttk.Checkbutton(ventana1, text="No necesario 2", command=disable_widgets)
    mensual_check_top1.grid(row=2, column=0)

    boton_flujo_3 = ttk.Button(ventana1, text="Aceptable")
    boton_flujo_3.grid(row=2, column=1)

    boton_flujo_4 = ttk.Button(ventana1, text="No aceptable")#,command=realizar_calibracion)
    boton_flujo_4.grid(row=2, column=2)
    

#Ventana Principal (root)
root = tk.Tk()
root.title("Ventana Principal") 
root.geometry("800x600")

# OPERADOR
operador_label = ttk.Label(root, text="Operador")
operador_label.grid(row=0, column=0)
operador_entry = ttk.Entry(root)
operador_entry.grid(row=0, column=1)

# STATUS. VALIDO INGRESO SOLO DE NUMEROS
status_label = ttk.Label(root, text="Status")
status_label.grid(row=1, column=0)
status_entry = ttk.Entry(root, validate="key")
status_entry['validatecommand'] = (status_entry.register(validate_numeric_input), '%P')
status_entry.grid(row=1, column=1)

# VALVE STATUS
valve_status_label = ttk.Label(root, text="Valve Status")
valve_status_label.grid(row=2, column=0)

    # si 0 cero check, desplegable deshabilitado 
cero_check = tk.IntVar()
cero_checkbox = ttk.Checkbutton(root, text="0 (cero)", variable=cero_check, command=disable_widgets)
cero_checkbox.grid(row=2, column=1)

    # desplegable para opciones de Valve Status que no son cero
options_var = tk.StringVar()
options = [" Otro valor ","01011 : Derivación", "01100 : Calentamiento/Aire limpio", "00000 : Medida", "00010 : Calibración medidor de flujo"]
dropdown = ttk.OptionMenu(root, options_var, *options)
dropdown.grid(row=2, column=2)

# APARIENCIA DEL FILTRO CON DESPLEGABLE
apariencia_filtro_label = ttk.Label(root, text="Apariencia Filtro")
apariencia_filtro_label.grid(row=3, column=0)

apariencia_filtro_options = ["APARIENCIA","Normal", "Achucharrado", "Marron"]
apariencia_filtro_var = tk.StringVar(value="")
apariencia_filtro_dropdown = ttk.OptionMenu(root, apariencia_filtro_var, *apariencia_filtro_options)
apariencia_filtro_dropdown.grid(row=3, column=1)

# FLUJO. 
flow_label = ttk.Label(root, text="Flujo")
flow_label.grid(row=4, column=0)
    # si 5lpm checkeado, deshabilito blank box
flow_check = ttk.Checkbutton(root, text="5lpm", command=disable_widgets)
flow_check.grid(row=4, column=1)
    #blank box
flow_entry = ttk.Entry(root)
flow_entry.grid(row=4, column=2)

# CINTA REEMPLAZADA
replacement_tape_label = ttk.Label(root, text="Cinta reemplazada?")
replacement_tape_label.grid(row=5, column=0)

    #checkbutton para cinta reemplazada
replacement_tape_check = ttk.Checkbutton(root, text="Si")
replacement_tape_check.grid(row=5, column=1)

# DIVISION
division_label = ttk.Label(root, text="------------------------------")
division_label.grid(row=7, column=1)

# TITULO CHECKLIST GENERAL
general_label = ttk.Label(root, text="CHECKLIST GENERAL")
general_label.grid(row=8, column=1)

# CHECKLIST GENERAL
big_checkbox_var = tk.IntVar()
big_checkbox = ttk.Checkbutton(root, width=0)
big_checkbox.grid(row=9, column=1, rowspan=4)

    # Hora actual + hora instrumento
hora_label = ttk.Label(root, text="Chequeo hora actual + instrumento")
hora_label.grid(row=9, column=0)

    # Inspeccion caño y manguera
mangueras_label = ttk.Label(root, text="Inspeccion caños y mangueras")
mangueras_label.grid(row=10, column=0)

    # Trampa agua interna
aguainterna_label = ttk.Label(root, text="Inspeccion trampa de agua interna")
aguainterna_label.grid(row=11, column=0)

    # Trampa agua externa
aguaexterna_label = ttk.Label(root, text="Inspeccion trampa de agua externa")
aguaexterna_label.grid(row=12, column=0)

# DIVISION
division_label = ttk.Label(root, text="------------------------------")
division_label.grid(row=13, column=1)

# CONTROL MENSUAL
general_label = ttk.Label(root, text="CONTROL MENSUAL")
general_label.grid(row=14, column=1) 

# create label for mangueras
verif_flujo = ttk.Label(root, text="Verificacion de flujo")
verif_flujo.grid(row=15, column=0)

control_mensual_check = ttk.Checkbutton(root, text="No necesario", command=disable_widgets)
control_mensual_check.grid(row=15, column=1)

boton_flujo_1 = ttk.Button(root, text="Aceptable")
boton_flujo_1.grid(row=15, column=2)

boton_flujo_2 = ttk.Button(root, text="No aceptable",command=realizar_calibracion)
boton_flujo_2.grid(row=15, column=3)

root.mainloop()

感谢您的评分
FQ
我在“Ventana principal”中使用了相同的逻辑,它起作用了,但是当我想在“Ventana 1”中使用时,我有下一个错误:
"NameError: name 'mensual_check_top1' is not defined"
我也试过创建全局变量,但都没有成功。

mzillmmw

mzillmmw1#

我能够使用您提供的代码复制您的问题。我相信我也能够解决您提到的问题,以获得您想要的结果。
“Ventana 1”代码的主要问题是所有变量都被分类在一个函数中,而“Ventana principal”不是这样的。这就是为什么它会给你“未定义”错误。要解决这个问题,你只需要将变量设为全局变量,这样就可以在disable_widgets函数中使用它们。下面是我为让它工作所做的更改。

#Ventana 1
def realizar_calibracion():

    ventana1 = tk.Toplevel(root)
    ventana1.geometry("300x100")
    ventana1.title("Ventana 1")

    verif_flujo_mensual = ttk.Label(ventana1, text="Verificacion de flujo")
    verif_flujo_mensual.grid(row=0, column=1)
 
    global mensual_check_top1 
    mensual_check_top1 = ttk.Checkbutton(ventana1, text="No necesario 2", command=disable_widgets)
    mensual_check_top1.grid(row=2, column=0)

    global boton_flujo_3
    boton_flujo_3 = ttk.Button(ventana1, text="Aceptable")
    boton_flujo_3.grid(row=2, column=1)

    global boton_flujo_4
    boton_flujo_4 = ttk.Button(ventana1, text="No aceptable")#,command=realizar_calibracion)
    boton_flujo_4.grid(row=2, column=2)

正如你所看到的,我刚刚把mensual_check_top1boton_flujo_3boton_flujo_4都变成了全局变量,这样它们就可以在realizar_calibracion函数的外部使用。

ldioqlga

ldioqlga2#

这是因为mensual_check_top1是在realizar_calibracion()内部定义的局部变量,所以它不能在函数外部访问。
我建议将disable_widgets()作为一个通用函数,如下所示:

def disable_widgets(checkvar, widgets):
    state = tk.DISABLED if checkvar.instate(['selected']) else tk.NORMAL
    for w in widgets:
        w.config(state=state)

然后更新这些command=disable_widgets如下:

...
def realizar_calibracion():
    ...
    mensual_check_top1 = ttk.Checkbutton(ventana1, text="No necesario 2",
                                         command=lambda: disable_widgets(mensual_check_top1, [boton_flujo_3, boton_flujo_4]))
    ...

...
cero_checkbox = ttk.Checkbutton(root, text="0 (cero)", variable=cero_check,
                                command=lambda: disable_widgets(cero_checkbox, [dropdown]))
...
flow_check = ttk.Checkbutton(root, text="5lpm",
                             command=lambda: disable_widgets(flow_check, [flow_entry]))
...
control_mensual_check = ttk.Checkbutton(root, text="No necesario",
                                        command=lambda: disable_widgets(control_mensual_check, [boton_flujo_1, boton_flujo_2]))
...
x7rlezfr

x7rlezfr3#

我相信如果在realizar_calibracion()函数之外创建mensual_check_top1,这个错误是可以避免的。
尝试将创建Checkbutton的行(如下所示)移到函数之外。您可以将.grid()命令保留在函数中,以便在执行函数之前不会显示按钮。

mensual_check_top1 = ttk.Checkbutton(ventana1, text="No necesario 2", command=disable_widgets)

**编辑:**将ventana1的定义和其他必要的小部件也移动到函数之外。因此,你的小部件和窗口是在函数之外定义的,并在函数内部配置/打包。这避免了使用global

相关问题