Feet to Meters objektorientiert realisiert.
This commit is contained in:
		
							
								
								
									
										171
									
								
								tk_first_steps/feet_classes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								tk_first_steps/feet_classes.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
from tkinter import *
 | 
			
		||||
from tkinter import ttk
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FeetToMeter(Tk):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.title("Feet to Meters")
 | 
			
		||||
        self.status = 1  # 1 - neue Eingabe, 2 - Eingabe verarbeitet
 | 
			
		||||
 | 
			
		||||
        # Event Handler (Validator) registrieren
 | 
			
		||||
        self.check_entry_wrapper = self.register(self.check_entry)
 | 
			
		||||
 | 
			
		||||
        self.create_styles()
 | 
			
		||||
        self.create_widgets()
 | 
			
		||||
        self.bind_events()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def create_styles(self):
 | 
			
		||||
        """ Erstellen der speziellen Stil-Konfigurationen.
 | 
			
		||||
 | 
			
		||||
        :return:
 | 
			
		||||
        """
 | 
			
		||||
        self.s = ttk.Style()
 | 
			
		||||
        self.s.configure('aFrame.TFrame', background="yellow")
 | 
			
		||||
        self.s.configure('bFrame.TFrame', background="green")
 | 
			
		||||
        self.s.configure('cFrame.TFrame', background="red")
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def create_widgets(self):
 | 
			
		||||
        """ Erstellen der Fenster-Bestandteile.
 | 
			
		||||
 | 
			
		||||
        :return:
 | 
			
		||||
        """
 | 
			
		||||
        # Rahmen im Hauptfenster (aus ttk für Farbanpassung)
 | 
			
		||||
        mainframe = ttk.Frame(self, padding="3 3 12 12")
 | 
			
		||||
        mainframe.grid(column=0, row=0, sticky=N+W+S+E)
 | 
			
		||||
 | 
			
		||||
        # mainframe darf sich ausdehnen.
 | 
			
		||||
        self.columnconfigure(0, weight=1)
 | 
			
		||||
        self.rowconfigure(0, weight=1)
 | 
			
		||||
 | 
			
		||||
        # Eingabefeld für Länge in feet
 | 
			
		||||
        self.feet = StringVar()
 | 
			
		||||
        feet_entry = ttk.Entry(mainframe, width=7, textvariable=self.feet,
 | 
			
		||||
                               validatecommand=(self.check_entry_wrapper, '%P'),
 | 
			
		||||
                               validate='key')
 | 
			
		||||
        feet_entry.grid(column=2, row=1, sticky=W+E)
 | 
			
		||||
 | 
			
		||||
        # Einheit-Label für Eingabefeld der Länge in feet
 | 
			
		||||
        ttk.Label(mainframe, text="feet").grid(column=3, row=1, sticky=W)
 | 
			
		||||
 | 
			
		||||
        # Label für Ausgabefeld der Länge in Metern
 | 
			
		||||
        ttk.Label(mainframe, text="ist äquivalent zu").grid(column=1, row=2, sticky=E)
 | 
			
		||||
 | 
			
		||||
        # Einheit-Label für Ausgabefeld der Länge in Metern
 | 
			
		||||
        ttk.Label(mainframe, text="Meter").grid(column=3, row=2, sticky=W)
 | 
			
		||||
 | 
			
		||||
        # Ausgabefeld für Länge in Metern
 | 
			
		||||
        self.meters = StringVar()
 | 
			
		||||
        meters_entry = ttk.Entry(mainframe, width=7, textvariable=self.meters)
 | 
			
		||||
        meters_entry.grid(column=2, row=2, sticky=(W, E))
 | 
			
		||||
        meters_entry.configure(state='readonly')  # keine Eingabe, aber selektierbar
 | 
			
		||||
 | 
			
		||||
        # Button für Berechnung
 | 
			
		||||
 | 
			
		||||
        button_calc = ttk.Button(mainframe, text="Berechne", command=self.calculate)
 | 
			
		||||
        button_calc.grid(column=3, row=3, sticky=W)
 | 
			
		||||
 | 
			
		||||
        # schönere Abstände
 | 
			
		||||
        for child in mainframe.winfo_children():
 | 
			
		||||
            child.grid_configure(padx=5, pady=5)
 | 
			
		||||
 | 
			
		||||
        # Statusbar
 | 
			
		||||
 | 
			
		||||
        self.frame_statusbar = ttk.Frame(self)
 | 
			
		||||
        self.frame_statusbar['relief'] = 'sunken'
 | 
			
		||||
        self.frame_statusbar['height'] = 12
 | 
			
		||||
        self.frame_statusbar['style'] = 'aFrame.TFrame'
 | 
			
		||||
        self.frame_statusbar.grid_propagate(0)  # Feste Größe an Grid-Packer weitergeben
 | 
			
		||||
        self.frame_statusbar.grid(column=0, row=1, sticky=W+S+E)
 | 
			
		||||
 | 
			
		||||
        # Setze Fokus in Eingabefeld
 | 
			
		||||
        feet_entry.focus()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def bind_events(self):
 | 
			
		||||
        """ Ereignisse an Kommandos binden.
 | 
			
		||||
 | 
			
		||||
        :return:
 | 
			
		||||
        """
 | 
			
		||||
        self.bind("<Return>", self.calculate)
 | 
			
		||||
        self.bind("<KP_Enter>", self.calculate)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def switch_status(self, new_status: int = None):
 | 
			
		||||
        """ Verändert den globalen Status
 | 
			
		||||
 | 
			
		||||
        :param new_status: neuer Statuswert
 | 
			
		||||
        :return: None
 | 
			
		||||
        """
 | 
			
		||||
        self.status
 | 
			
		||||
        if not new_status:
 | 
			
		||||
            if self.status == 1:
 | 
			
		||||
                self.status = 2
 | 
			
		||||
            else:
 | 
			
		||||
                self.status = 1
 | 
			
		||||
        else:
 | 
			
		||||
            self.status = new_status
 | 
			
		||||
        self.update_statusbar()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def update_statusbar(self):
 | 
			
		||||
        """ Passt die Farbe der Statuszeile an den Status an.
 | 
			
		||||
 | 
			
		||||
        :return: None
 | 
			
		||||
        """
 | 
			
		||||
        if self.status == 1:
 | 
			
		||||
            self.frame_statusbar['style'] = 'aFrame.TFrame'
 | 
			
		||||
        elif self.status == 2:
 | 
			
		||||
            self.frame_statusbar['style'] = 'bFrame.TFrame'
 | 
			
		||||
        else:
 | 
			
		||||
            self.frame_statusbar['style'] = 'cFrame.TFrame'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def calculate(self, *args):
 | 
			
		||||
        """ Berechnet aus der eingegebenen Länge in feet die Länge in Metern.
 | 
			
		||||
 | 
			
		||||
        :param args:
 | 
			
		||||
        :return: None
 | 
			
		||||
        """
 | 
			
		||||
        try:
 | 
			
		||||
            stringvalue = self.feet.get()
 | 
			
		||||
            stringvalue = stringvalue.replace(",", ".")
 | 
			
		||||
            value = float(stringvalue)
 | 
			
		||||
            m_value = 0.3048 * value
 | 
			
		||||
            m_value = round(m_value, 2)
 | 
			
		||||
            self.meters.set(m_value)
 | 
			
		||||
            # Berechnung abgeschlossen.
 | 
			
		||||
            self.switch_status(2)
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            pass
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def check_entry(self, what: str = ""):
 | 
			
		||||
        """ Validiert, ob Eingabe leer oder eine Fließkommazahl ist.
 | 
			
		||||
 | 
			
		||||
        :param what: str eingegebene Zeichenkette
 | 
			
		||||
        :return: boolean
 | 
			
		||||
        """
 | 
			
		||||
        self.switch_status(1)
 | 
			
		||||
        if what == "":
 | 
			
		||||
            # Nichts eingegeben
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            try:
 | 
			
		||||
                # DEBUG
 | 
			
		||||
                print(what)
 | 
			
		||||
                what = what.replace(',', '.')
 | 
			
		||||
                float(what)
 | 
			
		||||
                return True
 | 
			
		||||
            except ValueError:
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    app = FeetToMeter()
 | 
			
		||||
    app.mainloop()
 | 
			
		||||
		Reference in New Issue
	
	Block a user