Anfänger, Gui (tkinter) Python3, Entwurf

Code-Stücke können hier veröffentlicht werden.
Antworten
DaRiebi
User
Beiträge: 3
Registriert: Montag 17. Oktober 2016, 18:46

Hallo Leute,

wie im Titel beschrieben bin ich Python3 Anfänger. Ich versuche mir gerade die Sprache anzueignen. Ich versuche mich ausserdem gleich schon mal mit tkinter. Bitte keine Kommentare wie: "Arbeite ein Tutorial durch" oder ähnliches. ... --> Learning by doing <--- ist meine Einstellung. Denn etwas zu lernen was mich (im Moment) nicht interessiert, fällt mir ausgesprochen schwer :-/

Zu meinen Fragen:
--> Wie kann ich den Code verbessern (kürzen, performance, lesbarkeit usw).
--> Habe ich anderweitige Fehler gemacht (Logik stimmt nicht ect.).
--> Sonstige Anmerkungen. Bin sehr an eurer Kritik/Anregungen interessiert. Schliesslich möchte ich Python vernünftig nutzen.

Anmerkung zu meinem Code:
- Habe noch keine Bindings eingefügt
- Ein Entwurf, Oberfläche muss natürlich noch überarbeitet werden. Aber so ungefähr sollte die Software später aussehen.

Code: Alles auswählen

# -*- coding: utf-8 -*-
"""
Created on Sat Oct 15 20:42:45 2016

@author: flesh
"""

from tkinter import *
import math


"""------------------------------------
Create functions for open a new Window
------------------------------------"""


# Neues Fenster öffnen bei Button-klick 'Toolsammlung'
def tools_Click():
    toolsWindow = Toplevel()
    toolsWindow.title('Toolsammlung')
    toolsWindow.geometry('1200x450')
    
    """--------------
    Tools Window --> 'wurzel berechnen'
    --------------"""
    #Frame 1 erstellen
    frame1 = Frame(toolsWindow, width='1150')
    frame1.pack(fill='both')    
    
    
    labelWurzel = Label(frame1,
                          text='Zahl zur Wurzelberechnung eingeben:',
                          font='Monospace 12', bg='white', fg='black',
                          width='39', justify='left')
    labelWurzel.pack(side='left')
    
    
    wurzelEingabe = Entry(frame1, font='Monospace 12',
                          bg='brown', fg='black', width='13')
    wurzelEingabe.pack(side='left')
    
    # Funktion zur Quadratwurzelberechnung
    def wurzel_rechnen():
        try:
            awurzel = float(wurzelEingabe.get())
            bwurzel = math.sqrt(awurzel)
            labelErgebnisWurzel.config(text=bwurzel)
        except:
            labelErgebnisWurzel.config(text='Sie müssen eine Zahl eingeben!')
            
    
    buttonWurzel = Button(frame1, font='Monospace 12',
                          bg='white', fg='black', text='OK',
                          command=wurzel_rechnen)
    buttonWurzel.pack(side='left')
    
    
    labelErgebnisWurzel = Label(frame1, font='Monospace 12',
                                bg='brown', fg='black', justify='left',
                                width='35')
    labelErgebnisWurzel.pack(side='left')
    
    """Tools Window --> Hypothenuse rechteckiges 3eck
    """
    #Frame 2
    frame2 = Frame(toolsWindow, width='1150')    
    frame2.pack(fill='both')    
    
    def hypo_rechnen():
        try:
            ahypo = float(entryHypoA.get())
            bhypo = float(entryHypoB.get())
            c1hypo = ahypo*ahypo + bhypo*bhypo
            c2hypo = math.sqrt(c1hypo)
            labelHypErgebnis.config(text=c2hypo)
        except:
            labelHypErgebnis.config(text='Sie müssen Zahlen eingeben!')
    
    labelHypo = Label(frame2,
                          text='Länge der Hypothenuse berechnen',
                          font='Monospace 12', bg='white', fg='black',
                          width='39', justify='center')
    labelHypo.pack(fill='x')

    labelHypozahlA = Label(frame2,
                          text='Gegenkatheten Länge eingeben:',
                          font='Monospace 12', bg='white', fg='black',
                          width='39', justify='left')
    labelHypozahlA.pack(side='left')
    
    entryHypoA = Entry(frame2, font='Monospace 12',
                          bg='brown', fg='black', width='13')
    entryHypoA.pack(side='left')
    
    labelHypozahlB = Label(frame2,
                          text='Ankatheten Länge eingeben:',
                          font='Monospace 12', bg='white', fg='black',
                          width='39', justify='left')
    labelHypozahlB.pack(side='left')
    
    entryHypoB = Entry(frame2, font='Monospace 12',
                          bg='brown', fg='black', width='13')
    entryHypoB.pack(side='left')
    #Frame 3
    frame3 = Frame(toolsWindow, width='1150')    
    frame3.pack(fill='both')   
    
    buttonHypoOK = Button(frame3, font='Monospace 12',
                          bg='white', fg='black', text='OK',
                          command=hypo_rechnen)
    buttonHypoOK.pack(side='left')
    
    labelHypErgebnis = Label(frame3,
                          font='Monospace 12', bg='brown', fg='black',
                          width='39', justify='left')
    labelHypErgebnis.pack(side='left')
"""
------------------------------------
Create Main Window and Widgets
------------------------------------
"""
# Create main-window
mainwindow = Tk()
mainwindow.title('Riebis-Abbundsoftware')
mainwindow.geometry('600x450')


# Create labelh1
labelh1 = Label(mainwindow, text='free Zimmerer Abbundsoftware',
                font = 'Monospace 24', bg='brown', fg='black',
                justify='center')
labelh1.pack(fill=X, side='top')


# Trennlinien Label erzeugen
labelTrennlinie = Label(text='------------------------------',
                        font='Monospace 20')
labelTrennlinie.pack(fill=X, side='top')


# Create labelbottom
labelbottom = Label(mainwindow, text='@author: Fle$h', bg='brown',
                    fg='black', justify='center', font='Mono 8')
labelbottom.pack(fill=X, side='bottom')


#Button1 erstellen ( Sparren berehnen )
button1Sparren = Button(text='Sparren rechnen', font='Monospace 18',
                        justify='center', bg='lightgrey', fg='brown',
                        width='35')#command = einfügen
button1Sparren.pack()

#Button2 erstellen ( Schrägsparren berechnen )
button2GiebelSparren = Button(text='Schrägen Giebelsparren rechnen',
                              font='Monospace 18', justify='center',
                              bg='lightgrey', fg='brown',
                              width='35') #command = einfügen
button2GiebelSparren.pack()


#Button3 erstellen ( Gratsparren berechnen )
button3Gratsparren = Button(text='Gratsparren rechnen', bg='lightgrey',
                            fg='brown', justify='center',
                            width='35', font='Monospace 18')   #command = einfügen
button3Gratsparren.pack()


#Button4 erstellen ( Kehlsparren berechnen )
button4Kehlsparren = Button(text='Kehlsparren rechnen', bg='lightgrey',
                            fg='brown', justify='center',
                            font='Monospace 18', width='35') #command = einfügen
button4Kehlsparren.pack()


#Button5 erstellen ( Lattung & Eindeckung berechnen )
button5Lattung = Button(text='Lattung & Dacheindeckung rechnen',
                        bg='lightgrey', fg='brown', justify='center',
                        font='Monospace 18', width='35')   #command = einfügen
button5Lattung.pack()


#Button6 erstellen ( noch offen )
button6unklar1 = Button(text='sonstiges', width='35',
                        bg='lightgrey', fg='brown', justify='center',
                        font='Monospace 18')   #command = einfügen
button6unklar1.pack()


#Button7 erstellen zusatz Rechenfunktionen
button7Tools = Button(text='Toolsammlung', width='35',
                        bg='lightgrey', fg='brown', justify='center',
                        font='Monospace 18', command=tools_Click) #command = einfügen
button7Tools.pack()


#Button8 erstellen ( sonstiges )
button8Infos = Button(text='weitere Informationen', width='35',
                        bg='lightgrey', fg='brown', justify='center',
                        font='Monospace 18')   #command = einfügen
button8Infos.pack()


#Button9 erstellen ( noch offen )
"""
button9drunk = Button(text='Der Entwickler ist besoffen', width='35',
                        bg='lightgrey', fg='brown', justify='center',
                        font='Monospace 18')   #command = einfügen
button9drunk.pack()
"""

mainwindow.mainloop()

Bitte Kommentieren, danke --> DaRiebi
Zuletzt geändert von Anonymous am Montag 17. Oktober 2016, 19:29, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@DaRiebi: Tutorials durch*arbeiten* ist „learning by doing“, denn dabei tut man ja etwas statt einfach nur passiv irgend etwas zu lesen und auswending zu lernen.

Das gleich schon mal mit `tkinter` ist ein Problem denn So musst Du Funktionen, objektorientierte Programmierung (OOP), *und* ereignisbasierte Programmierung *gleichzeitig* lernen. Dabei ist OOP Voraussetzung für GUI-Programmierung. Und echte, saubere Funktionen sind Voraussetzung für OOP. Du versuchst den dritten Schritt vor dem ersten, beziehungsweise drei auf einmal. Und das geht schief, denn der erste ist im Code nicht zu sehen, und der zweite auch nicht. Es ist einfacher das der Reihe nach anzugehen.

Konkrete Punkte zu Quelltext: Sternchen-Importe sind Böse™. Damit holt man sich unkontrolliert Namen ins Modul so das es unübersichtlicher wird so was definiert ist und her kommt. Ausserdem besteht die Gefahr von Namenskollisionen.

Mehrzeilige Zeichenkettenliterale sind keine allgemeinen Kommentare. Die haben nur am Anfang von Modulen, Klassen- und Funktionsdefinitionen eine besondere Bedeutung und werden dort vom Compiler auch nicht ignoriert. Deshalb sind es auch keine Kommentare sondern Dokumentation die für den Benutzer des jeweiligen Objekts gedacht sind zu denen sie gehören. Als Kommentarzeichen kennt Python nur das '#'. Das wird auch für mehrzeilige Kommentare verwendet. Dafür sollte jeder brauchbare Editor entsprechende Unterstützung bieten.

Kommentare sollten nur verwendet werden um etwas zu schreiben was nicht offensichtlich im Code schon steht. Faustregel: Ein Kommentar beschreibt nicht *was* der Code macht, denn das beschreibt der Code ja schon, sondern *warum* der Code das so macht wie er es macht. Sofern das nicht offensichtlich ist.

Funktionen sollten keine Werte, ausser Konstanten, verwenden die nicht als Argument übergeben wurden. Und wenn es ein Ergebnis gibt, sollte das als Rückgabewert an den Aufrufer zurückgegeben werden.

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

Namen werden bei Konstanten KOMPLETT_GROSS geschrieben, bei Klassen in MixedCase, und alles andere klein_mit_unterstrichen. Funktionen und Methoden werden nach Tätigkeiten benannt, weil die etwas tun und um sie von ”passiven” Werten leichter unterscheiden zu können.

Die ganzen festen Grössenangaben für die GUI sollte man nicht machen. Einzig bei den Eingabefeldern macht es Sinn eine Breite anzugeben, weil das Widget ja nicht weiss wie viel an Eingabe vorgesehen ist.

Bei ``except`` sollte man immer angeben welche Ausnahmen man dort behandeln möchte, denn nur ganz selten kann man tatsächlich *alle* Ausnahmen, inklusive solcher die man gar nicht erwartet, sinnvoll behandeln. Der Code im ``try``-Block sollte dabei auch möglichst gering bleiben.

Es werden Zwischenergebnisse an komische Namen mit sinnfreien Zusätzen gebunden. `awurzel`, `bwurzel`, `ahypo`, `bhypo`, `c1hypo`, … sind alles keine guten Namen. Ein Name soll dem Leser vermitteln was der Wert dahinter im Kontext des Programms bedeutet.

GUI und Programmlogik (hier die Berechnungen) sind nicht getrennt.

Es werden mal Konstanten aus dem `tkinter`-Modul verwendet und mal Zeichenketten mit den Werten der Konstanten. Beispiel `tkinter.X` vs. 'x'.

Bei den Widgets wird bei der Erzeugung nicht immer das Elternwidget übergeben. Das ist nur dann zufällig richtig, wenn das Elternwidget das Hauptfenster ist. Wenn man also Änderungen an der Widgethierarchie vornehmen will, kann das zu Problemen führen.
DaRiebi
User
Beiträge: 3
Registriert: Montag 17. Oktober 2016, 18:46

Wow & oh verdammt,

erstamal danke für deine Zeit und Antwort.
Zweitens habe ich nur die Hälfte verstanden was du mir geschrieben hast. --> Wenn dem so ist, sollte ich wohl wirklich komplett bei 0 anfangen :-(
Drittens... wie lerne ich denn Python von grundauf 'Richtig'?... Habe nämlich nie wirklich viel Zeit
BlackJack

@DaRiebi: Um was zu lernen braucht man eigentlich immer Zeit. Um es dann auch noch gut zu beherrschen muss man es üben. Was wieder Zeit braucht. An der Stelle kann man immer ganz gut auf das Essay Teach Yourself Programming in Ten Years von Peter Norvig verlinken.

Du musst halt dran bleiben. An dem Prototyp kann man ja schon ganz gut die Richtung sehen. Jetzt könntest Du die Berechnungen zum Beispiel mal als eigenständige Funktionen schreiben. Dann ein wenig mit OOP beschäftigen. Das dann auf den GUI-Teil anwenden und die Berechnungsfunktionen damit verbinden. Vielleich nicht so viel ”toten” Code schreiben der (noch) nichts macht. Und jedes mal wenn Du mehr Funktionalität hinzufügst, schauen was Du dafür machen musst, wie sich das vom bereits vorhandenen Code unterscheidet, und was gleich oder sehr ähnlich ist, und wie man die Wiederholung des gleichen vermeiden könnte.
DaRiebi
User
Beiträge: 3
Registriert: Montag 17. Oktober 2016, 18:46

Bin nun doch überzeugt zuerst einmal ein Tutorial durchzugehen.

wird zwar einige Zeit dauern, aber wenn ich soweit bin, werde ich einen überarbeiteten Code posten.

Danke nochmal.
DaRiebi
Holzer
User
Beiträge: 1
Registriert: Dienstag 15. November 2016, 16:33

http://www.python-kurs.eu/ finde ich ganz gut. Damit hab ich Grundlegendes gelernt. Tkinter is auch als extra Reiter dabei.
Antworten