3

I've been trying to learn Python language for fun and decided it would be best to do it with a project. Since I work in a beer factory, I thought it would be cool to create a simple GUI that would display all tanks on the factory along with each beer it holds and its current status. If I double-click on a tank, it would pop a new window allowing me to edit tank info, but I'm having trouble making the information from the child to display on the parent window (more specifically, I want to change a parent list's item from a combobox on child). Here's an image showing basically what I'm trying to accomplish:

enter image description here

I think that maybe the values are being passed correctly to the list, but they are not being updated to the correspondent Widget to be displayed. I tried calling .update(), .after() and .mainloop() on my function, but nothing changed.
I tried checking other answers, but I was actually hoping there is a way to solve this without resorting to Classes, as I don't quite understand them yet. Here's the simplest smallest version of my code that I could come up with:

import tkinter as tk  
from tkinter import ttk  
from PIL import Image, ImageTk  


def click_duplo_tfm(event):  # recognizes double-click on tanks and opens the specific window  
    if event.widget.extra == 'Widget TFM01':  
        abrir_janela('01', 1)  
    elif event.widget.extra == 'Widget TFM02':  
        abrir_janela('02', 2)  


def salvar_alteracoes():  
    print('THIS FUNCTION IS SUPPOSED TO PASS CHANGES TO PARENT WINDOW')  


def abrir_janela(num_tfm, ref):  # opens a new window to alter tank info  
    def manter_selecao_ceva(event):  
        global ceva_tqs  
        ceva_tqs[referencia] = opcao_ceva.get()  
        print(ceva_tqs[referencia])  

    def manter_selecao_status(event):  
        global status_tqs  
        status_tqs[referencia] = opcao_status.get()  
        print(status_tqs[referencia])  

    referencia = int(ref)  
    janela = tk.Toplevel(adega_grande)  
    janela.title('TFM-' + num_tfm)  
    janela.geometry('550x300')  
    tfm = Image.open(img_tqs[referencia])  
    tfm.thumbnail((300, 300), Image.ANTIALIAS)  
    photo_tfm = ImageTk.PhotoImage(tfm, master=janela)  
    label_tfm = tk.Label(image=photo_tfm, borderwidth=0, highlightthickness=0, master=janela)  
    label_tfm.image = photo_tfm  
    label_tfm.grid(column=1, rowspan=20, row=1)  
    qual_tfm = tk.Label(master=janela, text='TFM-' + num_tfm, font='Arial 24 bold')  
    qual_tfm.grid(column=2, row=1)  
    ceva = tk.Label(master=janela, text='Cerveja: ', font='Arial 20 bold')  
    ceva.grid(column=2, row=2, sticky='W')  
    ceva_selecionada = 'Ceva selecionada'  
    opcao_ceva = ttk.Combobox(master=janela, values=cervs_factory, state='readonly', textvariable=ceva_selecionada)  
    opcao_ceva.grid(column=3, row=2)  
    opcao_ceva.bind("<<ComboboxSelected>>", manter_selecao_ceva)  
    status = tk.Label(master=janela, text='Status: ', font='Arial 20 bold')  
    status.grid(column=2, row=3, sticky='W')  
    status_selecionado = 'Status selecionado'  
    opcao_status = ttk.Combobox(master=janela, values=('Fermentando', 'Maturando'), state='readonly', textvariable=status_selecionado)  
    opcao_status.grid(column=3, row=3)  
    opcao_status.bind("<<ComboboxSelected>>", manter_selecao_status)  
    botao_salvar_alteracoes = tk.Button(master=janela, text="Salvar alterações no TFM", command=salvar_alteracoes)  
    botao_salvar_alteracoes.grid(column=2, columnspan=2, row=4)  


# creates main window and tabs (there are 22 smaller tanks to be added later on second tab)  
gui = tk.Tk()  
gui.configure(background="white")  
gui.title("Acompanhamento de adegas")  
abas = tk.ttk.Notebook(gui)  
adega_grande = tk.Frame(abas)  
adega_pequena = tk.Frame(abas)  
abas.add(adega_grande, text='Adega Grande')  
abas.add(adega_pequena, text='Adega pequena')  
abas.grid()  

# list of all kinds of beer produced in the factory  
cervs_factory = ('VAZIO', 'Weiss', 'Vienna Lager')  

# list of images to show on the tanks  
img_tqs = ["",  
           "tq cheio Beer 1.png",    # TFM-01  
           "tq cheio Beer 2.png",       # TFM-02  
           ]              # TFM-12  

# list of which beer is currently on each tank  
ceva_tqs = ["",  
            cervs_factory[1],         # TFM-01  
            cervs_factory[2]]          # TFM-02  


# list of tank current status Fermenting/Maturing  
status_tqs = ["",  
              'Fermentando',    # TFM-01  
              'Maturando',      # TFM-02  
              ]              # TFM-12  


# ~~~~  TFM's Adega Grande  ~~~~ #  
font_titulo_tfm = 'Arial 14 bold'  # altera fonte e tamanho dos títulos dos TFM's  
font_cerv_e_status = 'Arial 12 bold'  # altera fonte e tamanho do tipo de cerveja e status dos TFM's  
tamanho_img_tqs = (250, 250)  # altera o tamanho das imagens dos TFM's, só considera o menor valor  

tfm01 = Image.open(img_tqs[1])  
tfm01.thumbnail(tamanho_img_tqs, Image.ANTIALIAS)  
photo_tfm01 = ImageTk.PhotoImage(tfm01)  
label_tfm01 = tk.Label(adega_grande, image=photo_tfm01, borderwidth=0, highlightthickness=0)  
label_tfm01.grid(column=1, row=0)  
legenda_tfm01 = tk.Label(adega_grande, text='TFM-01', font=font_titulo_tfm)  
legenda_tfm01.grid(column=1, row=1)  
ceva01 = tk.Label(adega_grande, text=ceva_tqs[1], font=font_cerv_e_status)  
ceva01.grid(column=1, row=2)  
status01 = tk.Label(adega_grande, text=status_tqs[1], font=font_cerv_e_status, fg='green')  
status01.grid(column=1, row=3)  
label_tfm01.bind('<Double-Button-1>', click_duplo_tfm)  
label_tfm01.extra = "Widget TFM01"  

tfm02 = Image.open(img_tqs[2])  
tfm02.thumbnail(tamanho_img_tqs, Image.ANTIALIAS)  
photo_tfm02 = ImageTk.PhotoImage(tfm02)  
label_tfm02 = tk.Label(adega_grande, image=photo_tfm02, borderwidth=0, highlightthickness=0)  
label_tfm02.grid(column=2, row=0)  
legenda_tfm02 = tk.Label(adega_grande, text='TFM-02', font=font_titulo_tfm)  
legenda_tfm02.grid(column=2, row=1)  
ceva02 = tk.Label(adega_grande, text=ceva_tqs[2], font=font_cerv_e_status)  
ceva02.grid(column=2, row=2)  
status02 = tk.Label(adega_grande, text=status_tqs[2], font=font_cerv_e_status, fg='blue')  
status02.grid(column=2, row=3)  
label_tfm02.bind('<Double-Button-1>', click_duplo_tfm)  
label_tfm02.extra = "Widget TFM02"  

abas.mainloop()    

I hope to be forgiven if my question/code got too long, I'm very new to coding and this is my first time asking for help. Also not very fluent in English, but I think you guys get the point of my problem here. Thank in advance for any insight.

1 Answer 1

1

It is indeed a lot easier if you use classes, but it is still doable with your current approach.

Basically you need to first store your brand/status labels to a container (like a list), and then when you spawn a Toplevel widget, pass a index so you know which labels you need to modify. Below is a minimum sample:

import tkinter as tk
from tkinter import ttk
from itertools import cycle

root = tk.Tk()
brands = ('VAZIO', 'Weiss', 'Vienna Lager')
status = ("Fermenting","Maturing")
beer_factory = cycle(brands)
beer_status = cycle(status)
beer = []

for i in range(6):
    a = tk.Label(root,text=f"TFM-0{i+1}",width=20)
    a.grid(row=0,column=i)
    b = tk.Label(root, text=next(beer_factory))
    b.grid(row=1, column=i)
    c = tk.Label(root, text=next(beer_status))
    c.grid(row=2, column=i)
    a.bind('<Double-Button-1>', lambda e, i=i: toplevel(e,i))
    beer.append([a,b,c])

def toplevel(event, i):
    top = tk.Toplevel()
    tk.Label(top,text="Beer factory").grid(row=0,column=0)
    tk.Label(top, text="Status").grid(row=1, column=0)
    com1 = ttk.Combobox(top,values=brands,state="readonly")
    com1.set(beer[i][1]["text"])
    com1.grid(row=0,column=1)
    com2 = ttk.Combobox(top,values=status,state="readonly")
    com2.set(beer[i][2]["text"])
    com2.grid(row=1,column=1)
    def finish():
        beer[i][1].config(text=com1.get())
        beer[i][2].config(text=com2.get())
        top.destroy()
    tk.Button(top,text="Finish",command=finish).grid(row=3,column=0,columnspan=2)

root.mainloop()

The <Double-Button-1> event is bound to the labels TFM-0X.

Sign up to request clarification or add additional context in comments.

1 Comment

That absolutely solved my problem. Thank you very much for the quick reply and precise answer! =D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.