ttk.Label funktioniert z.B. die textvariable nur im Hauptfenster aber in keinem Toplevel() Fenster

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
stonie69
User
Beiträge: 24
Registriert: Dienstag 11. Juni 2024, 17:56

Hi,

ich habe folgendes Problem, warum kann ich in einem Hauptfenster z.B. bei einem "ttk.Label" die Textvariable "textvariable=result" nicht abrufen?
[
Code Hauptfenster:

Code: Alles auswählen

from tkinter import *
import tkinter.ttk as ttk
import test

window = Tk()

result = StringVar()
result.set('Alter Wert')
label_1 = ttk.Label(window, textvariable=result).grid()

result.set('Neuer Wert')


def click():
    test.load()

ttk.Button(window, text="Click", command=click).grid()

window.mainloop()

Code im TopLevel-Fenster:

Code: Alles auswählen

from tkinter import *
import tkinter.ttk as ttk

def load():
    window = Toplevel()
    result = StringVar()
    result.set('Alter Wert')
    label_1 = ttk.Label(window, textvariable=result).grid()

    result.set('Neuer Wert')

    ttk.Button(window, text="Click").grid()
Der Button wird angezeigt da er über "text='Click'" bestückt wird.
Aber warum wird mir nichts angezeigt sobald die in einem TopLevel Fenster mache

Vielen dank für eure Hilfe schonmal!!!
Gruß Dirk
stonie69
User
Beiträge: 24
Registriert: Dienstag 11. Juni 2024, 17:56

Hi,

hab es selbst raus gefunden :-) lag daran, dass icham Ende den "win.mainloop()" vergessen habe im Toplevel-Fenster

Beste Grüße
Benutzeravatar
__blackjack__
User
Beiträge: 14000
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@stonie69: Das ist nicht die Lösung innerhalb eines Rückrufs aus der Hauptschleife noch mal die Hauptschleife aufzurufen. Das Problem ist das das lokale `result` am Ende der Funktion halt wieder verschwindet, wie das bei lokalen Variablen halt so ist. Für jede nicht-triviale GUI braucht man objektorientierte Programmierung (OOP) also muss eigene Klassen schreiben, damit man sich Zustand über Aufrufe hinweg merken kann.

Sternchen-Importe sind Böse™. Da holt man sich gerade bei `tkinter` fast 140 Namen ins Modul von denen nur ein kleiner Bruchteil verwendet wird. Auch Namen die gar nicht in `tkinter` definiert werden, sondern ihrerseits von woanders importiert werden. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Sirius3
User
Beiträge: 18252
Registriert: Sonntag 21. Oktober 2012, 17:20

*-Importe benutzt man nicht, weil man damit unkontrolliert Namen in den eigenen Namensraum schaufelt. Bei so kurzen Programmen macht die Aufteilung in mehrere Dateien noch keinen Sinn.
Alles sollte in Funktionen stehen, das Hauptprogramm üblicherweise in einer Funktion die main heißt. Damit vermeidet man globale Variablen.
Variablennamen sollten aussagekräftig sein, eine 1 an label_ ist das sicher nicht. `None` an eine Variable zu binden ist nicht sinnvoll.
Bei `grid` gibt man eine Zeile und Spalte an. Du möchtest wahrscheinlich eher pack benutzen.

Bei einer StringVar zweimal set aufzurufen bringt nichts, weil ja nur der letzte Wert gespeichert wird.

Dass der Wert von StringVar nicht gesetzt wird, ist mir auch neu; eine Alternative wäre es, alle StringVar-Objekte gleich in main anlegen und den jeweiligen Top-Level-Fenstern übergeben. Das hat auch den Vorteil, dass man diese Werte im Hauptprogramm auch verwenden kann.

Das ganze könnte dann so aussehen:

Code: Alles auswählen

import tkinter as tk
from tkinter import ttk
from functools import partial 

def click(root, result):
    window = tk.Toplevel(root)
    ttk.Label(window, textvariable=result).pack()
    ttk.Button(window, text="Click").pack()

def main():
    window = tk.Tk()

    result = tk.StringVar(window, 'Neuer Wert')
    result_toplevel = tk.StringVar(window, 'anderer Wert')
    ttk.Label(window, textvariable=result).pack()
    ttk.Button(window, text="Click", command=partial(click, window, result_toplevel)).pack()
    window.mainloop()


if __name__ == "__main__":
    main()
stonie69
User
Beiträge: 24
Registriert: Dienstag 11. Juni 2024, 17:56

Hi,

vielen Dank für die schnelle Antwort.
Das mit den * werde ich mir zu Herzen nehmen und das nicht mehr anwenden. Somit lerne ich auch was ich wofür brauch und kann es gezielter einsetzen. Danke

Ja das mit der OOP habe ich noch einiges auf zu holen und zu lernen!

Vielen Dank für eure Antworten.

Eine Frage noch
Ist es sinnvoll ttkbootstrap oder PyQt5, PyQt6oder eine andere Bibliothek zu verwenden oder lieber alles selbst über die tk oder ttk Bibliothek sich selbst zu erarbeiten.

Was könnt ihr mir als kurze Antwort mit auf den Weg geben oder einen Tipp mit welcher Bibliothek ich mich auseinander setzen sollte.
In der Hauptsache möchte ich Daten in einer MS SQL-Datenbank abrufen und mit einem TableView Element anzeigen lassen und die Daten etwas aufbereiten.

Gruß Dirk
Benutzeravatar
__blackjack__
User
Beiträge: 14000
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@stonie69: Bei einer Tabellenansicht würde ich was anderes als Tk nehmen, was solche Anzeigeelemente schon fertig anbietet. Mein persönlicher Favorit ist Qt, aber das ist letztlich auch eine Lizenzfrage.

Grundlagen OOP sollte man aber bei fast allen GUI-Rahmenwerken vorher drauf haben. Die sind ja in der Regel selbst auch sehr OOP-lastig.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
stonie69
User
Beiträge: 24
Registriert: Dienstag 11. Juni 2024, 17:56

Habe mir mal PyQt angeschaut und ein wenig gestöbert und festgestellt, dass es wie es mir scheint sehr C lastig zu schreiben ist. Tue mir da eher schwer da ich bis jetzt immer C vermieden habe und eher in der einfacheren Programmierung unterwegs war. VB, VBA und etwas .Net

Besten Dank dennoch für den Tipp

Grüße
Benutzeravatar
__blackjack__
User
Beiträge: 14000
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@stonie69: Was meinst Du mit „C lastig“? Das Rahmenwerk selbst ist in C++ geschrieben, und da so ziemlich alles von QObject erbt und damit eigentlich keine/kaum Werttypen vorkommen, und Speicherverwaltung über die Objekthierarchie läuft, fühlt sich das ähnlich wie Java oder C# an. Und fügt sich auch in Python ganz gut ein.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
stonie69
User
Beiträge: 24
Registriert: Dienstag 11. Juni 2024, 17:56

Ja genau so wie du es geschrieben hast. Ich tu mir da schwer. Werde mich erstmal mit einfacheren Dingen die mir vertrauter erscheinen voran hangeln. Aber wie gesagt bin in den Anfängen wird sich auch noch ändern. Schritt für Schritt. Auf alle Fälle herzlichen Dank.
Antworten