Python Tkinter «останавливает» цикл while внутри функции

#python #tkinter #python-multithreading

#python #tkinter #python-многопоточность

Вопрос:

У меня есть программа на Python, использующая Tkinter для отображения значения (var peso внутри capturarpeso() функции) в реальном времени. Но цикл while в capturarPeso() не работает, цикл работает только в первый раз, после чего скрипт «ожидает».

Если я удалю компонент TK, он будет работать отлично. Я упростил сценарий:

 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()
 

Есть идеи о том, как продолжить? Спасибо

Ответ №1:

Функция captuarPeso() имеет return оператор, который завершает цикл while, поэтому на экран выводится только 1 число.

Удаление return делает так, что ваша программа застревает в этом цикле while, который печатает только peso потому, что, когда вы выполняете hilo.join() с потоком, он фактически ожидает завершения потока, прежде чем продолжить, и поскольку мы избавились от возврата на первом шаге, поток никогда не завершается, и поэтому он снова застревает в потоке.цикл. Чтобы исправить это, я изменил ваш цикл while на while self.peso != -999: и после вызова .mainloop() вами set self.peso = -999 , который сообщит программе: пользователь вышел из интерфейса Tkinter, выйдите из моего цикла.

Поскольку вы использовали a class для вставки части вашего графического интерфейса tkinter, почему бы не вставить все это? Как правило, большинство людей поместили бы весь интерфейс tkinter в класс, я пошел дальше и реструктурировал программу для вас, но попытался оставить столько же, сколько оригинал, чтобы вы могли проанализировать его и посмотреть, как это работает.

 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()
 

Дайте мне знать, если вам нужно что-то объяснить, и счастливых праздников!