widgets examples python arrays user-interface tkinter radio-button

python - examples - tkinter sliders



Python: matrices de widgets de tkinter que cambian con clics de botones de radio (2)

Estoy trabajando en una GUI en Python usando tkinter. Estoy leyendo un archivo de texto y creando elementos de GUI dinámicamente basados ​​en las líneas del archivo de texto. Tengo una matriz para cada uno de mis tipos de elementos, que incluyen etiquetas, variables de botones de radio (StringVars) y círculos de colores (dibujados con create_oval). Mi objetivo es que cuando el usuario cambie un botón de radio de "no asignado" a "dentro" o "fuera", el círculo de color en esa línea cambie de amarillo a verde. Así es como se ve la GUI después de que se haya leído el archivo de texto:

Artículo 1: (o) en () fuera () no asignado (G)

Artículo 2: () en () fuera (o) no asignado (Y)

Actualmente, tengo un rastro en el radiobutton StringVars para poder llamar a un método cada vez que se cambia uno de los botones. Mi problema es descubrir qué botón de radio se cambió para poder cambiar el color del círculo en esa línea ...

Actualmente voy por la ruta de duplicar toda la matriz StringVar de radiobutton en una matriz global temporal. Cuando se llama a la función de rastreo, comparo la matriz temporal con lo que está actualmente en la matriz para descubrir dónde está el cambio. Duplico la matriz con: temp_radiobutton_vars = list (radiobutton_vars), pero no estoy seguro de si esta es la ruta correcta. Mi lista temporal y la lista actual siempre muestran los mismos resultados cuando obtengo () el StringVar, incluso después de haber cambiado el botón. Alguna idea sobre cómo solucionar esto, o tal vez hay un mejor método para hacer lo que estoy buscando hacer ...

Perdón por la explicación larga y no genial. Si alguien necesita más información o fragmentos de código, házmelo saber. ¡Gracias!


Parece que tienes una idea equivocada con Radiobuttons . Todos los Radiobuttons "conectados" deben tener el mismo valor de variable ; de esta manera, puede llamar a theVariable.get() y compararlo con el value de cada Radiobutton ; no debería necesitar una referencia a cada Radiobutton ; ni debe tener un StringVar para cada Radiobutton , solo cada línea.

Editar : he ampliado mi ejemplo para mostrar cómo funcionaría esto para más de una línea. Todo lo que cambió ahora es que verifico qué línea he pasado en mi devolución de llamada, y al usarla, sé qué línea actualizar (en su caso, qué lienzo para colorear). Es solo un procesamiento de lista 2D para verificar qué Radiobutton se selecciona en función de qué línea está emitiendo la devolución de llamada.

from Tkinter import * root = Tk() root.geometry("300x200+500+400") lines = [StringVar(), StringVar()] strings = [["Hello", "Stack", "Overflow"], ["Whats", "Going", "On"]] buttons = [[],[]] l1 = Label(root, text = "Selection: ", justify = LEFT) l1.grid(column = 0, row = 0, sticky = NW, padx = (0, 250)) l1.grid_propagate(False) l2 = Label(root, text = "Selection: ", justify = LEFT) l2.grid(column = 0, row = 4, sticky = NW, padx = (0, 250)) l2.grid_propagate(False) def process(line): global l1, l2, strings, lines if line == lines[0]: # Since lines[0] was passed in to the callback, we know to update line 0; # take that line''s label (or canvas in your case) updateLine = 0 updateLabel = l1 else: # Otherwise take the other line updateLine = 1 updateLabel = l2 # These operations are performed within if/elif/else to show how you coul # choose a different process for each Radiobutton: example, coloring a canvas differently if lines[updateLine].get() == strings[updateLine][0]: # This means the first button of whatever line was selected updateLabel.config(text = "Selection: %s" %strings[updateLine][0]) elif lines[updateLine].get() == strings[updateLine][1]: # This means the second button of whatever line was selected updateLabel.config(text = "Selection: %s" %strings[updateLine][1]) else: # You get the idea updateLabel.config(text = "Selection: Bet you thought I''d say %s" %strings[updateLine][2]) # Must have a seperate row number because with multiple lines, we can''t simply use ''i'' or ''j'' rowNum = 1 for i in range(len(lines)): for j in range(len(strings[i])): buttons[i].append(Radiobutton(root, text = strings[i][j], variable = lines[i], value = strings[i][j], command = lambda line = lines[i]: process(line))) buttons[i][j].grid(column = 0, row = rowNum, sticky = NW) rowNum +=1 rowNum += 2 root.mainloop()


Hay muchas formas de resolver este problema. Como ya está usando rastros de variables, quizás la solución más simple es pasar el índice del artículo de lienzo a la devolución de llamada. Puede usar lambda o functools.partial para esta tarea. Tampoco podría usar trazas variables, sino asociar un comando con cada botón de radio. En ambos casos, simplemente necesita decirle a la devolución de llamada qué índice debe operar.

En el siguiente ejemplo, la devolución de llamada toma como referencia una variable y el índice del elemento de lienzo. Obtiene el valor, busca el color en una tabla y luego configura el elemento canvas:

def on_radiobutton(var, index): value = var.get() color = {"in": "green", "out": "red", "unassigned": "yellow"} self.canvas.itemconfigure(index, fill=color[value])

Esta es la forma en que la traza se configura utilizando lambda (tenga en cuenta que tkinter envía automáticamente name1 , name2 y op para cada traza):

var = tk.StringVar() rb0 = tk.Radiobutton(..., variable=var, value="in", text="in") rb1 = tk.Radiobutton(..., variable=var, value="out", text="out") rb2 = tk.Radiobutton(..., variable=var, value="unassigned", text="not assigned") var.trace("w", lambda name1, name2, op, index=i, var=var: on_radiobutton(var, index))