tkinter Labelaktualisierung

Fragen zu Tkinter.
Antworten
samaha73
User
Beiträge: 8
Registriert: Freitag 13. Dezember 2019, 12:09

Hallo zusammen,

ich probiere schon ewig an einer Lösung rum und bekomme es einfach nicht hin. Ich hab bisher nur in Funktionen "gedacht" und möchte mich nur mehr in Richtung Klassen aufmachen.
Kurz zu meiner gewünschten Funktion. Ich habe einen Ablauf mit Sollwerten und Istwerten und möchte diese darstellen. Die Istwerte ändern sich ja und nähern sich dem Sollwert. Also muss ich ja die Labels automatisch aktualisieren. Mit der Funktion in meinem Programm 'ram_available(label)' geht das auch. Nur mit der von mir vermutlich total bescheuert angelegten Klasse will das nicht gehen. Vielleicht kann mir ja jemand von euch auf die Sprünge helfen. Diese RAM Prozentgeschichte dient lediglich dazu Werte zu erfassen die sich halt im Laufe des Programms ändern.

Was mach ich denn da falsch? Wenn ich die Methode update z.B. new nenne dann kommts zu folgender Fehlermeldung: AttributeError: 'Label' object has no attribute 'new'

Wenn ich die Update Methode aufrufe passiert nichts.. als auch der print nicht.

Wäre nett wenn mich jemand von meiner Leitung hebt und Licht ins Dunkel bringen kann..


Code: Alles auswählen

import tkinter as tk
from tkinter import *
import psutil

refresh = 500

class My_label:
    def __init__(self, label,  window, text, separator, value, unit, row, column, columnspan, sticky):
        self.label = label
        self.window = window
        self.text = text
        self.separator = separator
        self.value = value
        self.unit = unit
        self.row = row
        self.column = column
        self.columnspan = columnspan
        self.sticky = sticky

    def create(self):
        label = tk.Label(self.window)
        #
        status = self.text + self.separator + str(self.value) + ' ' + self.unit
        label.config(text=status)
        #
        label.grid(row=self.row,
                   column=self.column,
                   columnspan=self.columnspan,
                   sticky=self.sticky
                   )
        return label # tkinter Label 

    def update(self):
        x = float(ram_check())
        print(x) # debug
        status = self.text + self.separator + str(x) + ' ' + self.unit
        self.label.config(text=status)
        self.label.after(500, self.update)

def ram_check():
    # you can have the percentage of used RAM
    ram_percent = psutil.virtual_memory().percent
    return ram_percent


def ram_available(label):
    def check():
        x = float(ram_check())
        status = 'Virtual Memory:\t'+str(x)+'%'
        label.config(text=status)
        label.after(refresh, check)
    check()

def main():
    # Create a window
    root = tk.Tk()
    root.title("label test")
    root.geometry("300x80")

    actual_value_VM = My_label(
            'actual_value_VM',
            root,
            'Virtual Memory',
            ':\t',
            float(ram_check()),
            '%',
            1,
            0,
            1,
            'W'
            ).create()
    

    label_test = tk.Label(root,bg="#000000", fg="#FFFFFF")
    ram_available(label_test)
    label_test.grid(row=2, column=0, sticky="W")


    button_refresh = tk.Button(
        root,
        text='refresh',
        command=actual_value_VM.update()
        )
    button_refresh.grid(row=3,column=0)
    root.mainloop()

if __name__ == '__main__':
    main()

Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@samaha73: Du musst als `command` die Methode mitgeben, nicht die Methode aufrufen und deren Rückgabewert übergeben. Die Klammern müssen weg.

Edit: Die `create()`-Methode ist komisch. Nach der `__init__()` sollte man ein benutzbares Objekt haben, denn das erstellen passiert schon davor und `__init__()` initialisiert das Objekt. Danach dann noch mal was erstellen macht keinen Sinn. Und vor allem kommst Du so nie an das Objekt weil das ja nirgends an einen Namen gebunden wird.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
samaha73
User
Beiträge: 8
Registriert: Freitag 13. Dezember 2019, 12:09

Hallo __blackjack__

hm ok.. Danke schon mal fürs antworten. Werde mal mit nem Namen rumprobieren..

Ich habe versucht das Label direkt in der '__init__()' zu erstellen aber da bekomme ich diese Fehlermeldung 'TypeError: __init__() should return None, not 'Label'
' daher hab ich das mit dem create() gemurkst.. :)

nochmals danke für so eine schnelle Antwort..

... deine Wohnort ist echt mega :))))
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Die `__init__()` initialisiert das Objekt, die gibt nichts zurück. Der Aufruf der Klasse gibt das Objekt zurück das `__init__()` übergeben wird. Der Aufruf der Klasse ist nicht der Aufruf der `__init__()`. Der ist nur Teil von dem ganzen was da abläuft.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Simon.M
User
Beiträge: 11
Registriert: Freitag 19. November 2021, 18:45

Hatte mal das selbe Problem, dafür muss das Label aktualisiert werden, das kann man mit
LABELNAME.grid_forget() machen
Könnte so aussehen:

Code: Alles auswählen

def ram_available(label):
    def check():
        x = float(ram_check())
        status = 'Virtual Memory:\t'+str(x)+'%'
        label.grid_forget()
        label = Label(text=status)
        label.grid(row=xx, column=xx)
Vielleicht hilft das
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Simon.M: Das macht doch aber überhaupt keinen Sinn ständig alte Label weg zu werfen um an der selben Stelle neue Label zu erstellen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

@Simon.M: Und das definieren einer Funktion in einer Funktion würde ich auch in Frage stellen.
samaha73
User
Beiträge: 8
Registriert: Freitag 13. Dezember 2019, 12:09

Komisch nur dass genau das mit der Funktion in der Funktion klappt..
Ich verstehe nicht was ich falsch mache.. hab das nochmal mit der Uhrzeit versucht.. Versuch 1 geht Versuch2 mit Klassen geht nicht.. Beim 2. Versuch wird die Uhrzeit nur beim Starten geschrieben aber die Uhr läuft nicht, weil diese label.after Geschichte nicht hinbekomme..

Geht das halt einfach nicht??? :?: Ich dachte halt es wäre so viel einfacher und übersichtlicher Labels, Buttons etc zu erstellen.. Also wenn es denn funktionieren würde.. :lol:



Versuch1:

Code: Alles auswählen

import time
import datetime
import tkinter as tk


def uhrzeit():
    now = datetime.datetime.now()
    text = f"{datetime.datetime.now():%H:%M:%S}"
    return text


def label_uhrzeit(label):
    def check():
        status = uhrzeit()
        label.config(text=status)
        label.after(500, check)
    check()


def main():
    root = tk.Tk()
    root.title('GUI Test Function')

    label1 = tk.Label(root)
    label_uhrzeit(label1)
    label1.grid(row=0, column=0)

    root.mainloop()

if __name__ == '__main__':
    main()

Versuch2

Code: Alles auswählen

import time
import datetime
import tkinter as tk

class Display:
    def __init__(self, title):
        self.root = tk.Tk()
        self.title = title
        self.root.title(title)


class Label:
    def __init__(self, window, text1, value, row, column, columnspan, sticky):
        self.window = window
        self.text1 = text1
        self.value = value
        self.row = row
        self.column = column
        self.columnspan = columnspan
        self.sticky = sticky
        
        self.create()

    def create(self):
        self.label = tk.Label(self.window)
        status = self.text1 +str(self.value)
        self.label.config(text=status)
        #
        self.label.grid(row=self.row,
                   column=self.column,
                   columnspan=self.columnspan,
                   sticky=self.sticky
                   )
        
        return self.label # tkinter Label 
    

def uhrzeit():
    now = datetime.datetime.now()
    text = f"{datetime.datetime.now():%H:%M:%S}"
    return text


def main():

    display = Display('GUI Test Label Class')

    label_uhrzeit = Label(display.root, 'Time: ', uhrzeit(), '1', '1', '1', 'W')
    
    display.root.mainloop()

if __name__ == '__main__':
    main()
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

*-Importe benutzt man nicht, weil damit Dein Namensraum mit Namen überflutet werden.
Widgets sollten sich nicht selbst positionieren, das grid gehört daher ins main.
Du übergibst value, aber `update` aktualisiert value gar nicht; dafür hast Du den Aufruf von ram_check und das Erzeugen des Status-Strings doppelt.
Statt Strings per + zusammen, sondern benutzt Formatstrings.
Da seperator nur in Zusammenhang mit text benutzt wird, kann man beide zusammenfassen. Noch besser wäre es, einfach nur einen Formatstring zu übergeben.

Bleiben also von den vielen Argumenten in __init__ gerade noch 2 übrig.

Code: Alles auswählen

import tkinter as tk
import psutil

def ram_check():
    return float(psutil.virtual_memory().percent)


class UpdatingLabel(tk.Label):
    def __init__(self, window, text, callback, refresh=500):
        tk.Label.__init__(self, window)
        self.text = text
        self.refresh = refresh
        self.callback = callback
        self.update()

    def update(self):
        self['text'] = self.text.format(self.callback())
        self.after(500, self.update)


def main():
    # Create a window
    root = tk.Tk()
    root.title("label test")
    root.geometry("300x80")

    actual_value_vm = UpdatingLabel(root, 'Virtual Memory:\t{} %', ram_check)
    actual_value_vm.grid(row=1, column=0, sticky=tk.W)
    root.mainloop()

if __name__ == '__main__':
    main()
samaha73
User
Beiträge: 8
Registriert: Freitag 13. Dezember 2019, 12:09

Wow, viele geniale Informationen :) das muss ich erstmal verarbeiten...

Vielen Dank!!!!
Simon.M
User
Beiträge: 11
Registriert: Freitag 19. November 2021, 18:45

sparrow hat geschrieben: Montag 22. November 2021, 06:36 @Simon.M: Und das definieren einer Funktion in einer Funktion würde ich auch in Frage stellen.
Hatte mich nur auf die bestimmte Funktion fokussiert, ist mir auch später aufgefallen das Funktionen in Funktionen nicht viel sind machen.
Antworten