Erstellen eines Fensters mit Rahmen und Label

Fragen zu Tkinter.
Antworten
Tommilein
User
Beiträge: 10
Registriert: Mittwoch 16. September 2020, 03:56

Hallo,

ich habe mir Klassen gebastelt, um ein Fenster, einen Rahmen und ein Label zu erstellen. Nun soll mit dem Code im Hauptprogramm ein Fenster (root) sowie im Fenster ein Rahmen (frame) erstellt werden, und letztlich ein Label im Rahmen. Dummerweise wird mir nur das gelbe Label angezeigt, der Frame nicht. Wenn ich auf das Label verzichte, klappt es mit dem roten Rahmen. Gelbes Label im roten Rahmen funktioniert, wie gesagt, nicht.
Wäre klasse, wenn mir jemand weiterhelfen könnte.

Code: Alles auswählen

from tkinter import * 
from tkinter import ttk

class WindowCreator(Tk):

    def __init__(self):
        Tk.__init__(self)

class FrameCreator(Frame):
    
    def __init__(self, root):
        self.root = root
        Frame.__init__(self, root)
        self.pack()

class LabelCreator(Label):

    def __init__(self, parent):
        self.parent = parent
        Label.__init__(self, parent)
        self.pack()


#Erstellen des Fensters 'root':
root = WindowCreator()

#Erstellen des Rahmens 'frame':
frame = FrameCreator(root)
frame.config(width=200, height=150, background='red')

#Erstellen des Labels 'label':
label = LabelCreator(frame)
label.config(width=7, height=5, background = 'yellow')

root.mainloop()
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Benutze keine *-Importe. Damit holst du dir unkontrolliert hunderte Namen in den eigenen Nebenraum. WindowCreator ist kein Fenstermacher sondern ein Fenster. FrameCreator ist kein Rahmenmacher und LabelCreator macht kein Label. Alle Klassen sind total sinnlos. Schau die hier im Forum Beiträge zu tkinter an, da siehst du Beispiele wie man richtige Klassen definiert.
Du packst das Label in den Frame. Damit ist das Label exakt so groß wie der Frame und vom roten Hintergrund siehst du nichts mehr.
Benutzeravatar
__blackjack__
User
Beiträge: 14085
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Tommilein: Weitere Anmerkungen:

`ttk` wird importiert, aber nirgends verwendet.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Kommentare sollen dem Leser einen Mehrwert über den Code geben. Faustregel: Kommentare beschreiben nicht *was* der Code macht, denn das steht da bereits als Code, sondern warum er das macht. Sofern das nicht offensichtlich ist.

Eine `__init__()` die nur die `__init__()` der Basisklasse aufruft kann man sich sparen, das passiert auch so. Damit wäre die `WindowCreator`-Klasse leer, würde sich also im Verhalten überhaupt gar nicht von einem `Tk`-Objekt unterscheiden. Man kann da also direkt das `Tk`-Objekt verwenden.

Beim `FrameCreator` ist der Argument- und Attributname `root` unnötig einschränkend, denn da kann ja jedes beliebige Container-Widget übergeben werden, und nicht nur das Hauptfenster. Es müsste also `master` heissen, wie bei allen anderen Widgets auch. Auch beim `LabelCreator` würde ich es `master` nennen, denn das ist nun mal der Argumentname bei allen Widgets für dieses Argument.

Man braucht das nicht an ein Attribut binden, denn das passiert bereits in der ziemlich weit oben stehenden Basisklasse `BaseWidget`. Dieses Attribut gibt es also bereits nachdem man die `__init__()` der jeweiligen Basisklasse aufgerufen hat.

Widgets layouten sich nicht selbst. Der `pack()`-Aufruf gehört also nicht in die `__init__()` des Widgets sondern ausserhalb, nachdem ein Exemplar davon erstellt wurde.

Wenn man das `master`-Attribut setzen und den `pack()`-Aufruf aus der `__init__()` von `FrameCreator` und `LabelCreator` nimmt, dann bleibt wie beim `WindowCreator` nur der Aufruf der `__init__()` von der Basisklasse übrig, also eine `__init__()` die keinen Sinn macht. Und damit kann man dann auch diese beiden Klassen einfach weg lassen und direkt `Frame` und `Label` an ihrer Stelle verwenden.

Dann stellt sich noch die Frage warum nach dem erstellen von Frame- und Label-Objekt jeweils die `config()`-Methode aufgerufen wird, denn das kann man ja bereits alles *beim* erstellen angeben.

Damit bleibt dann von dem Programm das hier übrig:

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk


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

    frame = tk.Frame(root, width=200, height=150, background="red")
    frame.pack()

    label = tk.Label(frame, width=7, height=5, background="yellow")
    label.pack()

    root.mainloop()


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten