Frame Verwendung TKinter

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
knut
User
Beiträge: 14
Registriert: Freitag 18. August 2017, 15:23

Python 3

Hallo,

Ich beschäftige mich z.Zt mit der Objekt Orientierten Programmierung. Einem Tkinter Lehrbuch entnahm ich die folgende Demonstration, die zu Beginn eines Programms einen in der Größe und Lage änderbaren Frame auf dem Bildschirm zeigt:

from tkinter import Tk , BOTH
from tkinter.ttk import Frame

class Example(Frame ):

def __init__(self , parent ):

Frame.__init__(self , parent)
self.parent = parent
self.initUI ()

def initUI(self ):

self.parent.title("Simple")
self.pack(fill=BOTH , expand=True)

def main ():

root = Tk()
root.geometry("250 x150 +300+300")
app = Example(root)
root.mainloop ()

if __name__ == '__main__ ':

print('Hier')
main()



1. Ist meine Annahme richtig, daß dieser Frame im Laufe des Kursus dann mit weiteren Fenstern z.B. für Text, Tabellen, Bildern o.a. ausgefüllt werden kann ?

2. Dann wäre nach meinem Verständnis dieser Bildschirm der Hauptbildschirm von dem im Programm andere Bildschirme mit denselben (vom Hauptprogramm „geerbten“ ) Eigenschaften des Frames angezeigt werden. Ist diese Annahme richtig?

2. Wie werden die weiteren Fenstern aufgerufen? (bedeutet dies die Klasse Frame ansprechen? )

3. Beim Aufruf der DEMO erhalte ich keinerlei Reaktion der Anzeige. Was habe ich verkehrt gemacht?

Trotz meines fortgeschrittenen Alters möchte ich nicht aufgeben und bitte deshalb um Euer wohlwollendes Verständnis für Opas dumme Fragen. Ich möchte aber von Anfang an, mir eine solide Wissensbasis schaffen, auf der ich aufbauen kann.

Dank im voraus für Eure Hilfsbereitschaft !
Freundliche Grüße
Knut
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hallo Knut,

bitte benutz in Zukunft Code-Boxen um Code zu posten. Sonst entfallen die Einrueckungen, und wir koennen deinen Code nicht lesen.

Zu deinen Fragen:

1) da du den Kurs nicht nennst, ist es schwierig diese Frage mit Bestimmtheit zu beantworten.
2) Verstehe ich nicht so ganz. Ein Bildschirm ist etwas physisches. Ein Frame ist eine rechteckige Zone *auf* einem Bildschirm. Bei tkinter immer in einem Fenster, welches in deinem Fall "root" genannt ist (ein sogenanntes TopLevel Window). Wer was wie wann davon erbt ist mir nicht ersichtlich.
3) Aehnlich wie die beiden Fragen vorher fragst du nach der Richtigkeit von Annahmen ueber zukuneftige Verwendungen, die in einem uns unbekannten Kurs stattfinden. Kann man also leider auch nichts zu sagen.
4) Da du keine Code-Boxen nutzt, kann man das Beispiel so nicht so einfach laufen lassen, und dementsprechend auch nicht recht beurteilen, ob es ueberhaupt geht, ob du etwas falsch machst, etc.

Eine allgemeine Anmerkung: so wie ich den Code sehe, finde ich ihn schwierig. Der Aufruf von "pack" im Konstruktor des abgeleiteten Frames ist ein Anti-Pattern. Also zwar nicht technisch falsch (es ist ja machbar), aber halt eine schlechte Idee. Falls das ein Hinweis auf die Qualitaet des restlichen Kurses darstellt, bin ich skeptisch.
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

in der offiziellen Python-Doku ist ein Beispiel, wo der Frame direkt mit Widgets gefüllt wird: https://docs.python.org/3.5/library/tki ... ld-program

Grundsätzlich halte ich GUI-Programmierung auch nicht ideal zum lernen von OOP (unter Python), weil bei GUIs ja gerne mit Vererbung, `super()` und ggf. Überschreiben von Methoden gearbeutet wird. Was man IMHO aber erst versteht, wenn man die Grundlagen von OOP verstanden hat.

Gruß, noisefloor
knut
User
Beiträge: 14
Registriert: Freitag 18. August 2017, 15:23

Hallo Ihr beiden!

Vielen Dank für die schnelle Antwort, die mir wieder einmal klar macht, daß ich noch einen weiten Weg vor mir habe, um alles richtig zu machen. Deshalb ein besonderer Dank für Eure Geduld und auch für Deinen Hinweis, lieber noisefloor, auf das Beispiel im Internet.

Natürlich habe ich versucht, Object Oriented Programming zu verstehen. Vor ca 50 Jahren hatte ich viel mit Programmierern zu tun, die Vorträge über Nassy Schneidermann etc. hielten. Zum großen Teil sind meine damaligen Verständnisbemühungen längst überholt,. Sie blockieren aber das Verstehen und Denken in den modernen heutigen Katagorien. Davon will ich weg. Wenn ich die OOP richtig interpretiere, dann haben wir damals ein großes EDV Programm aufgebaut, indem Funktionen sequentiell abgearbeitet wurden. Den Funktionen wurden sowohl Variable als auch Schalter ( z.B. If A = "ZZZZ" then mach B ...) übergeben.
Wechselte die Aufgabe, mußte ein neuer Bildschirm vorhanden sein (z.B. Eingabe der Kasse oder Eingabe der Produkte / Tonnage oder Anzeige des relevanten Ergebnisses)

Die OOP benutzt "Objekte", die "mit einander sprechen". Bedeutet das, daß statt einzelner Aufgaben bezogener Bildschirme ein Bildschirm z.B. mit einem definierten Frame programmiert wird, in dem die notwendigen Widgets aufgabenentsprechend gewechselt werden?

In dem Fall wäre der Unterschied zum damaligen mir bekannten System des Aufrufs der Funktionen nur eine sprachliche Barriere des Denkens, weil in der OOP auch die Funktionen als Object bezeichnet werden, die über zu übergebende Attribute gesteuert werden.

Bitte habt Verständnis dafür, daß ich das Lehrbuch nicht nennen möchte. Der Autor hat sich sehr bemüht und verdient es nicht, daß ich ihn bloß stelle. Wenn das Demoprogramm nicht läuft ist das sicherlich meiner Dummheit zuzuschreiben.

Leider hatte ich den Sinn und die Nutzung der Code-Eingabe nicht verstanden. Hoffentlich habe ich es diesmal richtig gemacht. Das folgende Demoprogramm des Lehrbuches soll einen Frame anzeigen. Ich habe das aber nicht fertig gebracht:

[Codebox=python file=Unbenannt.py][/Codebox

from tkinter import Tk , BOTH
from tkinter.ttk import Frame

class Example(Frame ):

def __init__(self , parent ):

Frame.__init__(self , parent)
self.parent = parent
self.initUI ()

def initUI(self ):

self.parent.title("Simple")
self.pack(fill=BOTH , expand=True)

def main ():

root = Tk()
root.geometry("250 x150 +300+300")
app = Example(root)
root.mainloop ()

if __name__ == '__main__ ':

print('Hier')
main()

Vielen Dank im voraus!

Gruß
Knut
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das mit der Code-Box hast du nicht hinbekommen. Du musst den gesamten Code markieren, und *dann* das Dropdown hier oben ("Code auswaehlen") benutzen.

Dazu kann man auch die Vorschau bemuehen, um daran rumzuschrauben, bis es passt.

Und der Sinn ist doch recht klar:

if bedingung:
tuwas()

ist kaputtes Python.

Code: Alles auswählen

if bedingung:
     tuwas()
funktioniert. Ohne Codebox werden die in Python wichtigen Einrueckungen verhunzt, und damit ist ueber die Lauffaehigeit deines Programmes halt immer noch nichts zu sagen.

Was deine Bedenken bezueglich des Autors des Buches angeht: ich finde das schwer nachvollziehbar. Der Autor hat etwas veroeffentlicht. Das diese Veroeffentlichung einer kritischen Betrachtung unterzogen wird, ist ja nun etwas voellig normales. Es gibt eine Reihe von Kursen und Buechern, von denen hier - aus guten Gruenden - abgeraten wird. Und gegen deren schlechten Praktiken hier immer wieder angearbeitet werden muss, weil sie dem Verstaendnis von Anfaengern nachhaltig abtraegig sind. Ob es sich bei eben diesem Kurs ebenfalls um einen solchen handelt, kann jetzt aber keiner von uns beurteilen.

Die Konsequenz aus deiner Zurueckhaltung ist also, das ich oder andere hier mehr Arbeit investieren muessen. Das finde *ich* unverdient, und werde dementsprechend auch genau ueberlegen, ob ich dazu Lust habe.

Last but not least: deine Gedanken zum Thema OO sind mir immer noch nicht wirklich klar. ZB ist Sequentialitaet davon nicht betroffen, auch OO-Programme arbeiten Anweisungen sequentiell ab.

Auch was du mit wechselnder Aufgabe, Bildschirm, und Co meinst ist mir nicht klar.

Um dir mal ein Beispiel zu zeigen, welches eine der zentralen Eigenschaften der OO darstellt - die Polymorphie https://de.wikipedia.org/wiki/Polymorph ... ammierung), hier ein paar Zeilen Code:

Code: Alles auswählen

import random

class Auto:

     def fahre(self):
            print("Gas geben")

class Rad:

     def fahre(self):
            print("tritt in die Pedale")


def auf_zur_arbeit(fortbewegungsmittel):
     fortbewegungsmittel.fahre()


def main():
      ding = random.choice([Rad(), Auto()]) # was auch immer Mutti mir morgens uebriggelassen hat
      auf_zur_arbeit(ding)

if __name__ == "__main__":
      main()
Hier zeigt sich, das OO es erlaubt, die Erwartung an eine bestimmte Funktionalitaet - in diesem Fall ein generelles Konzept von Fortbewegungsmittel - von der konkreten Implementierung zu trennen. auf_zur_arbeit will einfach nur etwas haben, das fahren kann. *Wie* es das macht, kapseln Auto und Rad jeweils auf ihre Art ab, und stellen eine gleichfoermige Schnittstelle bereit durch die gleich aussehende Methode "fahre".

Das ist natuerlich ein kuenstliches Mininmalbeispiel.
knut
User
Beiträge: 14
Registriert: Freitag 18. August 2017, 15:23

Hallo deets,
Vielen Dank für deine Antwort.

Deine Sicht der Bekanntgabe von Autoren damit auch andere das Buch eventuell nutzen können, kam mir nicht in den Sinn.
Der Autor des von mir benutzten Tkinter Tutorials ist:

Jan Bodnar. Sein Buch wurde im Internet als PDF - Datei zum Kauf angeboten. Es erschien mir aufgrund des Inhaltsverzeichnisses und der persönlichen Angaben sowie der Ausführlichkeit vertrauenswürdig.

Deine Demo zur Funktionsweise von OOP ist sehr hilfreich. Sie zeigte den Weg, den ich nun versuchen werde zu gehen.

Vielen Dank auch für die Anweisung zur Nutzung der Codebox. Ich hoffe, daß nun und in Zukunft alles richtig wiedergegeben wird:

[Codebox=python file=testframe.py]
[/
from tkinter import Tk , BOTH
from tkinter.ttk import Frame

class Example(Frame ):

def __init__(self , parent ):

Frame.__init__(self , parent)
self.parent = parent
self.initUI ()

def initUI(self ):

self.parent.title("Simple")
self.pack(fill=BOTH , expand=True)

def main ():

root = Tk()
root.geometry("250 x150 +300+300")
app = Example(root)
root.mainloop ()

if __name__ == '__main__ ':

main()]

Das Demo sollte einen Frame anzeigen. Was machte ich falsch?
Wo wird name definiert, der die Funtion main aufruft? (Ich hatte in meiner letzten Anfrage ein print verlangt, um das zu sehen. Aber auch dieser Befehl wurde nicht angezeigt.)

Bitte verzeih mir die Mühe, die ich Dir mache. Im voraus vielen, vielen Dank

Gruß
Knut
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Einrückungen sind wichtig, daher auch der Hinweis auf die richtige Benutzung der CodeBox. Bei Fehlern wäre eine möglichst exakte Fehlerbeschreibung hilfreich, wie z.B. das Programm tut gar nichts und beendet sich sofort wieder.

Bei Dir ist alles ab `def main` zu weit eingerückt.

Code: Alles auswählen

from tkinter import Tk , BOTH
from tkinter.ttk import Frame

class Example(Frame):
    
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()

    def initUI(self):
        self.parent.title("Simple")
        self.pack(fill=BOTH, expand=True)

def main():
	root = Tk()
	root.geometry("250x150+300+300")
	app = Example(root)
	root.mainloop()

if __name__ == '__main__ ':        
	main()
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hallo Knut,

du hast die Codebox leider noch nicht ganz hinbekommen. Die Schritte sind

- Code einkopieren
- Alle Zeilen markieren, im Zweifel lieber eine davor und danach zuviel
- auch "Code auswaehlen" klicken, und Python auswaehlen.

Dann mit "Vorschau" pruefen, ob alles geklappt hat. Nimm dir einfach mal die Zeit einen Test-Post zu machen, wo du nur mit der Vorschau arbeitest, bis der Code so formatiert ist, wie du es hier zB von Sirius und mir siehst. Den Post kannst du entweder als test markieren, oder dann einfach doch nicht abschicken, um dich damit vertraut zu machen.

Bezueglich des Buches schaue ich mal nach, was ich da so entdecken kann.
knut
User
Beiträge: 14
Registriert: Freitag 18. August 2017, 15:23

Lieber deets, lieber sirius,

So langsam wird es mir peinlich,daß man mit über 80 so doof ist. Aber dagegen hilft nur eins Menschen wie ihr beiden und der feste Wille zur Besserung. Ich kann Euch nur immer wieder danken für Eure Geduld und versprechen, nach meinen Möglichkeiten das Meinige zu versuchen. Ich habe wie vorgeschlagen experimentiert und hoffe, daß der Code nun verwendungsfähig ist:

Code: Alles auswählen

from tkinter import Tk , BOTH
from tkinter.ttk import Frame

class Example(Frame ):
    
    def __init__(self , parent ):
        
        Frame.__init__(self , parent)
        self.parent = parent
        self.initUI ()

    def initUI(self ):
        
        self.parent.title("Simple")
        self.pack(fill=BOTH , expand=True)

    def main ():
       
        root = Tk()
        root.geometry("250 x150 +300+300")
        app = Example(root)
        root.mainloop ()

    if __name__ == '__main__ ':        

        main()
        
Nochmals vielen Dank.

Herzlichen Gruß
Knut
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und schon hat sich die Mühe ausgezahlt!

In Python sind die Einrückungen sehr wichtig. Und was man jetzt sieht ist, das du sowohl die main-Funktion als auch den Ausführungsschutz (das ist das Ding mit if __name__…) zu tief eingerückt hast. Dadurch gehören die jetzt zur Klasse, und machen nix bei der Ausführung.

Schau dir mal weiter oben Sirius Code an, da hat er die Einrückungen richtig gemacht. Probier mal das nachzubauen. Wichtig ist beim programmieren auch ein geeigneter Editor, der dir bei solchen Dingen hilft. Zb indem du ganze Blöcke markieren und geschlossen ein bzw ausrücken kannst, ohne das sie innere Struktur verlieren.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Einrückungen sind wichtig. Bei Dir ist alles ab `def main` zu weit eingerückt. Außerdem sind einige Leerzeichen zu viel, beim String "250x150+300+300" und beim String '__main__'. Computer legen viel Wert auf Exaktheit. Da scheitert es manchmal an kleinen Details.

Code: Alles auswählen

from tkinter import Tk , BOTH
from tkinter.ttk import Frame
 
class Example(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        self.initUI()
 
    def initUI(self):
        self.parent.title("Simple")
        self.pack(fill=BOTH, expand=True)
 
def main():
    root = Tk()
    root.geometry("250x150+300+300")
    app = Example(root)
    root.mainloop()
 
if __name__ == '__main__':
    main()
Die Leerzeilen und die restlichen Leerzeichen, die zu viel sind, machen nur das Lesen für Menschen schwierig.
knut
User
Beiträge: 14
Registriert: Freitag 18. August 2017, 15:23

Hallo Ihr beiden!

Habt Ihr den dumpfen Knall vernommen, der soeben aus dem Frankfurter Raum zu hören war?
Der Frame wurde in voller Schönheit angezeigt und versetzt Opa in eine vorweihnachtliche Stimmung. Ich habe durch Euch viel gelernt. (Ihr habt einen Orden verdient). Jetzt machen die nächsten Schritte wieder Spaß.

Danke, danke, danke für Eure Mühe, Euer Verständnis und Eure Geduld !!

Gruß
Knut
Antworten