Как использовать параметр в рекурсивном методе классов

Я пытаюсь подготовить кадр tkinter, чтобы отобразить некоторые значения разных датчиков. Я бы использовал объекты класса для повторного использования кода, указав конкретные параметры каждого датчика. Ниже приведена часть моего кода:

Код работает, и я получаю метку с обновлением значения на регулярной основе, но я бы создал только экземпляры класса LabelScreen с другим текстом и значениями, переданными в качестве параметров.

class LabelScreen1():
    def __init__(self, parent, text_label, string_var):
        self.string_var = string_var
        larghezza_titolo = 19
        larghezza_labels = 5
        altezza_labels = 2        
        imb_pulsantey = int(1*h)        
        imb_pulsantex = int(1.5*w) 

        self.labelA = tk.Label(
            labels_frame,
            text = "fff",

            width = larghezza_labels,
            height = altezza_labels,
            highlightthickness=2,
            highlightcolor="DodgerBlue2",
            highlightbackground='DodgerBlue2',
            font= ('ObliviousFont',int(h*5)),
            fg="DodgerBlue2",
            background = "gray3",
            pady = imb_pulsantey,
            padx = imb_pulsantex
            )

        self.labelA.place(x=int(w*10), y=int(h*10))

        self.labelA_title = tk.Label(
            labels_frame,
            text = text_label,

            width = larghezza_titolo,
            font= ('ObliviousFont',int(h*1.5)),
            fg="DodgerBlue2",
            background = "gray3",
            )

        self.labelA_title.place(in_=self.labelA, relx=.5, y=int(h*2),anchor="c")        
        self.update_label()

    def update_label(self):        
        self.labelA.configure(text=self.string_var.get())#prex_hot)
        self.labelA.after(1000, self.update_label)

class LabelScreen2():
    def __init__(self, parent, text_label):
        larghezza_titolo = 19
        larghezza_labels = 5
        altezza_labels = 2        
        imb_pulsantey = int(1*h)        
        imb_pulsantex = int(1.5*w) 


        self.labelA = tk.Label(
            labels_frame,
            text = "fff",
            width = larghezza_labels,
            height = altezza_labels,
            highlightthickness=2,
            highlightcolor="DodgerBlue2",
            highlightbackground='DodgerBlue2',
            font= ('ObliviousFont',int(h*5)),
            fg="DodgerBlue2",
            background = "gray3",
            pady = imb_pulsantey,
            padx = imb_pulsantex
            )

        self.labelA.place(x=int(w*30), y=int(h*10))

        self.labelA_title = tk.Label(
            labels_frame,
            text = text_label,
            width = larghezza_titolo,
            font= ('ObliviousFont',int(h*1.5)),
            fg="DodgerBlue2",
            background = "gray3",
            )

        self.labelA_title.place(in_=self.labelA, relx=.5, y=int(h*2),anchor="c")        
        self.update_label()

    def update_label(self):        
        self.labelA.configure(text=temp1)
        self.labelA.after(1000, self.update_label)

class LabelScreen3():
    def __init__(self, parent, text_label):
        larghezza_titolo = 19
        larghezza_labels = 5
        altezza_labels = 2        
        imb_pulsantey = int(1*h)        
        imb_pulsantex = int(1.5*w) 


        self.labelA = tk.Label(
            labels_frame,
            text = "fff",
            borderwidth=int(h*0.3),            
            width = larghezza_labels,
            height = altezza_labels,
            highlightthickness=2,
            highlightcolor="DodgerBlue2",
            highlightbackground='DodgerBlue2',
            font= ('ObliviousFont',int(h*5)),
            fg="DodgerBlue2",
            background = "gray3",
            pady = imb_pulsantey,
            padx = imb_pulsantex
            )

        self.labelA.place(x=int(w*50), y=int(h*10))

        self.labelA_title = tk.Label(
            labels_frame,
            text = text_label,
            width = larghezza_titolo,
            font= ('ObliviousFont',int(h*1.5)),
            fg="DodgerBlue2",
            background = "gray3",
            )

        self.labelA_title.place(in_=self.labelA, relx=.5, y=int(h*2),anchor="c")        
        self.update_label()

    def update_label(self):        
        self.labelA.configure(text=temp2)
        self.labelA.after(1000, self.update_label)

def change_value_randomly(string_var):
    import time
    import random

    while True:
        #string_var.set(random.randint(-10, 10))
        string_var.set(prex_hot)
        time.sleep(1)

radice = tk.Tk()

H=int(radice.winfo_screenheight())
W=int(radice.winfo_screenwidth())
h=int(H/100)
w=int(W/100)
prex_hot=tk.StringVar()

t = threading.Thread(target=change_value_randomly, args=(prex_hot,))
t.start()
screen_resolution = str(W)+'x'+str(H)
radice.geometry(screen_resolution)
labels_frame = tk.Frame(
            radice, background = "black")

labels_frame.pack(fill=tk.BOTH, expand=True)
#labels_frame.pack_propagate(0)
#radice.overrideredirect(1)
label1 = LabelScreen1(radice, "PRESSURE HOT WATER", prex_hot)
label2 = LabelScreen2(radice, "TEMP. EXTERNAL NH")
label3 = LabelScreen3(radice, "TEMP. BOILER")

radice.mainloop()

Проблема связана с методом update_label(self), который я использую для обновления текста (значение датчика) на экране. В этом методе вы видите переменную prex_hot, которую я бы поставил в качестве параметра класса. Я пробовал с: def update_label(self, parameter), но так как это рекурсивно, я получаю ошибку рекурсии. Я бы передал параметр объекту класса, но пробовал по-разному, никогда не работал. Вероятно, причина в том, что параметр сам по себе является переменной, или, возможно, я ошибаюсь в другом месте. Любая помощь (простите меня за ошибки новичка)?


person user3072083    schedule 25.08.2019    source источник
comment
возможно, вам следует добавить это в __init__(..., prex_hot): и self.prex_hot = prex_hot, а затем configure(text=self.prex_hot), но это может не сработать, если эта переменная сохраняет текст, потому что он будет копировать текст, а не сохранять ссылку на исходную переменную, поэтому позже у нее не будет доступа к новому тексту в переменной. Это будет StrVar или элемент в списке, чтобы использовать ссылку на переменную.   -  person furas    schedule 25.08.2019
comment
это не работает. Я уже пытался использовать StrVar (даже DoubleVar), но он не обновлял переменную, поэтому я следовал методу обновления. Просто для информации, я использовал pygame вместо tkinter, и у меня всегда было любое необходимое решение. Tkinter более легкий (вот причина этого более позднего выбора), но, на мой взгляд, слишком ограничен.   -  person user3072083    schedule 26.08.2019


Ответы (1)


В этом примере используется StringVar.

Thread запускает код, который использует string_var.set(value) для установки случайного значения в StringVar.

В то же время LabelScreen использует string_var.get() для получения значения из того же StringVar и отображения его в метке.

import tkinter as tk
import threading

class LabelScreen():

    def __init__(self, parent, text_label, string_var):
        self.string_var = string_var

        larghezza_titolo = 19
        larghezza_labels = 5
        altezza_labels = 2        
        imb_pulsantey = int(1*h)        
        imb_pulsantex = int(1.5*w) 
        screen_resolution = str(W)+'x'+str(H)
        parent.geometry(screen_resolution)
        self.labels_frame = tk.Frame(parent, background="black")

        self.labels_frame.pack(fill=tk.BOTH, expand=True)
        self.labels_frame.pack_propagate(0)

        self.labelA = tk.Label(
            self.labels_frame,
            text = "fff",
            borderwidth=int(h*0.3),
            width = larghezza_labels,
            height = altezza_labels,
            relief="raised",
            font= ('ObliviousFont',int(h*5)),
            fg="SteelBlue1",
            background = "gray7",
            pady = imb_pulsantey,
            padx = imb_pulsantex
        )

        self.labelA.place(x=int(w*10), y=int(h*10))

        self.labelA_title = tk.Label(
            self.labels_frame,
            text = text_label,
            borderwidth=int(h*0.3),
            width = larghezza_titolo,
            font= ('ObliviousFont',int(h*1.5)),
            fg="SteelBlue1",
            background = "gray7",
        )

        self.labelA_title.place(in_=self.labelA, relx=.5, y=int(h*2),anchor="c")        
        self.update_label()

    def update_label(self):        
        self.labelA.configure(text=self.string_var.get())
        self.labelA.after(1000, self.update_label)

# ---------------------------------------------------------

def change_value_randomly(string_var):
    import time
    import random

    while True:
        string_var.set(random.randint(-10, 10))
        time.sleep(1)


radice = tk.Tk()

H=int(radice.winfo_screenheight())
W=int(radice.winfo_screenwidth())
h=int(H/100)
w=int(W/100)
#radice.overrideredirect(1)

prex_hot = tk.StringVar() # after creating `tk.Tk()`

# after creating `StringVar()` but before `mainloop()`
t = threading.Thread(target=change_value_randomly, args=(prex_hot,))
t.start()

label1 = LabelScreen(radice, "PRESSURE HOT WATER", prex_hot)


radice.mainloop()
person furas    schedule 26.08.2019
comment
Спасибо, ваше предложение работает. Я отредактировал исходный код выше. Вы можете увидеть небольшие изменения (tk.Frame вне класса и создание трех классов), которые я сделал ранее. Но самое главное — это реализация вашего предложения. Теперь я обновляю переменную prex_hot, но не понимаю, как использовать поток для создания моих переменных в качестве параметров класса. Я бы создал экземпляры со всеми параметрами внутри них и имел бы только один класс. Спасибо еще раз - person user3072083; 27.08.2019