Search code examples
pythontkinterpython-multithreading

Python Tkinter "stop" a while loop inside function


I have a Python program using Tkinter to show a value (var peso inside capturarpeso() function) in realtime. But the while loop in capturarPeso() doesn't work, the loop only works the first time then the script is "waiting".

If I remove the TK component, it works perfectly. I simplified the script:

import tkinter as tk
from tkinter import *
import threading
import random

def capturarPeso():
    global peso
    while True:
        peso = random.randrange(0, 101, 2)
        print (peso)
        return(peso)

def capturarPesoHilo():
    hilo = threading.Thread(target=capturarPeso, name=None, group=None, args=(), kwargs=None, daemon=True)
    hilo.start()
    hilo.join()

class ActualizarPeso(Label):
    def __init__(self, parent, *args, **kwargs):
        Label.__init__(self, parent, *args, **kwargs)
        self.tick()

    def tick(self):
        self.config(text= peso)
        self.after(500, self.tick)

capturarPesoHilo()

window = tk.Tk()
window.title('Capturador pesos')
window.resizable(width=False, height=False)

pesoLabel = ActualizarPeso(window, font="Arial 60", fg="red", bg="black", width=8, height= 1)
pesoLabel.grid(row=15, column=0)

window.mainloop()

Any ideas on how to continue? Thank you


Solution

  • The function captuarPeso() has a return statement which will exit the while loop, this is why you only get 1 number printed to the screen.

    Removing the return makes it so your program is stuck in that while loop which only prints peso because when you do hilo.join() to a thread it's actually waiting for the thread to exit before continuing, and since we got rid of the return in the first step, the thread never exits and so it's again stuck in a loop. To fix this I changed your while loop to while self.peso != -999: and after calling .mainloop() you set self.peso = -999 which will tell the program: the user has exited the Tkinter interface, exit my loop.

    Since you used a class to put some of your tkinter gui in, why not put it all in? Generaly most people would put the entire tkinter interface in a class, I've gone ahead and restructured the program for you but tried to leave as much as the original by itself so you can analyze it and see how it works.

    import tkinter as tk
    import threading
    import random
    import time
    
    
    class ActualizarPeso:
    
        def __init__(self):
            self.window = tk.Tk()
            self.window.title('Capturador pesos')
            self.window.resizable(width=False, height=False)
            self.pesoLabel = self.crearLabel()
            self.peso = 0
            self.tick()
    
            hilo1 = self.capturarPesoHilo()
            self.window.mainloop()
            self.peso = -999
            hilo1.join()
    
        def crearLabel(self):
            pesoLabel = tk.Label(self.window, font="Arial 60", fg="red", bg="black", width=8, height=1)
            pesoLabel.grid(row=15, column=0)
            return pesoLabel
    
        def tick(self):
            self.pesoLabel.config(text=self.peso)
            self.pesoLabel.after(500, self.tick)
    
        def capturarPeso(self):
            while self.peso != -999:
                self.peso = random.randrange(0, 101, 2)
                print(self.peso)
                time.sleep(1)
    
        def capturarPesoHilo(self):
            hilo = threading.Thread(target=self.capturarPeso)
            hilo.start()
            return hilo
    
    
    ActualizarPeso()
    

    Let me know if you need something explained, and Happy Holidays!