DGHK Ostercamp 2024 : Python
„Fenster, Knöpfe, Schieberegler und Grafikeffekte unter Python“
1. Python Crashkurs Beispiele
1.1 Variablen
anzahl_kekse = 123 preis_pro_keks = 1.20 kosten = anzahl_kekse * preis_pro_keks print(kosten) # => 147.6
1.2 Listen
sachen = ["buch", "brille", "kekse"] print(sachen) # => ['buch', 'brille', 'kekse'] erste_sache = sachen[0] print(erste_sache) # => buch dritte_sache = sachen[2] print(dritte_sache) # => kekse vierte_sache = sachen[3] print(vierte_sache) # => IndexError: list index out of range sachen.append("saft") vierte_sache = sachen[3] print(vierte_sache) # => saft
1.3 Dictionaries
person = { "name": "Maria", "alter": 15, "hobbies": ["Lesen", "Programmieren", "Tischtennis"] } print(person) # => {'name': 'Maria', 'alter': 15, 'hobbies': ['Lesen', 'Programmieren', 'Tischtennis']} name = person["name"] print(name) # => Maria alter = person["alter"] print(alter) # => 15 hobbies = person["hobbies"] print(hobbies) # => ['Lesen', 'Programmieren', 'Tischtennis'] person["wohnort"] = "Berlin" wohnort = person["wohnort"] print(wohnort) # => Berlin
1.4 Funktionen
def addiere(a, b): return a + b c = addiere(3, 4) print(c) # => 7
1.5 for-Schleifen
for zaehler in range(10): print(zaehler) # => zählt von 0 bis 9 obst = ["äpfel", "birnen", "bananen"] for element in obst: print("ich mag", element) # => ich mag äpfel # => ich mag birnen # => ich mag bananen
1.6 while-Schleifen
while(True): print("Bitte gib etwas ein! Beenden mit 'ENDE'") eingabe = input() # Die Eingabe wird mit "ENDE" verglichen: if eingabe == "ENDE": # Wenn der Vergleich wahr ist, verlassen wir die Schleife: break print("Du hast", eingabe, "eingegeben!") print("Das Programm ist vorbei")
1.7 Module
import random as rand z1 = rand.random() print(z1) # => Zufallszahl zwischen 0 und 1 z2 = rand.randrange(10, 20) print(z2) # => Zufallszahl zwischen 10 und 19
2. PySimpleGUI Beispiele
2.1 Das Minimalbeispiel
import PySimpleGUI as sg sg.set_options(font=("Courier", 30)) layout = [ [sg.Input(key="-EINGABE-")], [sg.Button("Übertragen", key="-UEBERTRAGEN-")], [sg.Input(key="-AUSGABE-", disabled=True)], [sg.Button("Beenden", key="-BEENDEN-")] ] window = sg.Window("Minimalbeispiel", layout, size=(300, 250)) while True: event, values = window.read() if event == sg.WIN_CLOSED or event == "-BEENDEN-": break if event == "-UEBERTRAGEN-": text_eingabe = values["-EINGABE-"] window["-AUSGABE-"].update(text_eingabe) window.close()
2.2 Das Minimalbeispiel, kommentiert
# Import des PySimpleGUI-Moduls unter dem Kürzel sg import PySimpleGUI as sg # Wir setzten die Option 'font' auf ("Courier", 30), # damit die Schrift nicht so winzig ist! sg.set_options(font=("Courier", 30)) # Das Layout ist eine zweidimensiopnale Tabelle! # Jede Zeile der Tabelle ist eine Zeile im Layout! # Das Schlüsselwortargument "key" legt den Namen des Elementes fest. layout = [ # Das Eingabefeld [sg.Input(key="-EINGABE-")], # Der Button "Übertragen" [sg.Button("Übertragen", key="-UEBERTRAGEN-")], # Das Ausgabefeld [sg.Input(key="-AUSGABE-", disabled=True)], # Der Button "Beenden" [sg.Button("Beenden", key="-BEENDEN-")] ] # Hier erzeugen wir das Hauptfenster. # Das zweite Argument ist immer das layout! window = sg.Window("Minimalbeispiel", layout, size=(300, 250)) # Die Hauptschleife unseres Programms: while True: # window.read() liefert das Event: welcher Knopf wurde gedrückt? # und values: ein Verzeichnis (genauer: Dictionary), das die Zustände # aller GUI Elemente enthält. event, values = window.read() # Wenn das Event sg.WIN_CLOSED war (das Hauptfenster wurde geschlossen) # oder der "Beenden"-Knopf gedrückt wurde... if event == sg.WIN_CLOSED or event == "-BEENDEN-": # springe aus der Hauptschleife break # Wenn der "Übertragen"-Knopf gedrückt wurde... if event == "-UEBERTRAGEN-": # wird der inhalt des Eingabefeldes kopiert... text_eingabe = values["-EINGABE-"] # und in das Ausgabefeld geschrieben window["-AUSGABE-"].update(text_eingabe) # Diese Zeile wird nur erreicht, wenn die Hauptschleife verlassen wurde. # Sie schließt das Hauptfenster, falls es nicht schon geschlossen ist: window.close()
2.3 Das erweiterte Minimalbeispiel
import PySimpleGUI as sg sg.set_options(font=("Courier", 30), background_color="yellow", element_background_color="#32CD32", button_color=('white', 'blue')) layout = [ [sg.Input(key="-EINGABE-")], [sg.Button("Übertragen", key="-UEBERTRAGEN-")], [sg.Button("Testknopf", key="-TEST-")], [sg.Combo(["Apfel", "Birne", "Banane"], default_value="Banane", enable_events=True, key="-AUSWAHL-")], [sg.Slider(range=(0, 255), default_value=128, orientation='h', enable_events=True, key="-REGLER-")], [sg.Input(key="-AUSGABE-", disabled=True)], [sg.Button("Beenden", key="-BEENDEN-")] ] window = sg.Window("Minimalbeispiel", layout, size=(500, 450)) while True: event, values = window.read() # print("event:", event) # print("values:", values) if event == sg.WIN_CLOSED or event == "-BEENDEN-": break if event == "-UEBERTRAGEN-": text_eingabe = values["-EINGABE-"] window["-AUSGABE-"].update(text_eingabe) if event == "-TEST-": window["-AUSGABE-"].update("Testknopf gedrückt!") if event == "-AUSWAHL-": nachricht = values["-AUSWAHL-"] + " ausgewählt!" window["-AUSGABE-"].update(nachricht) if event == "-REGLER-": nachricht = "Regler: " + str(values["-REGLER-"]) window["-AUSGABE-"].update(nachricht) window.close()
2.4 Das erweiterte Minimalbeispiel, kommentiert
import PySimpleGUI as sg sg.set_options(font=("Courier", 30), # Farbangaben per Html-Farbnamen oder im Hex-Code: background_color="yellow", element_background_color="#32CD32", # Button-Farben für gedrückt und losgelassen: button_color=('white', 'blue')) layout = [ [sg.Input(key="-EINGABE-")], [sg.Button("Übertragen", key="-UEBERTRAGEN-")], # NEU: Testknopf [sg.Button("Testknopf", key="-TEST-")], # NEU: Combo (=Drop-Down-Menü): # erstes Argument immer Liste mit Auswahlmöglichkeiten [sg.Combo(["Apfel", "Birne", "Banane"], # Standard Wert: default_value="Banane", # Die Liste soll Events erzeugen bei Nutzung: enable_events=True, key="-AUSWAHL-")], # NEU: Slider: # Wertebereich: [sg.Slider(range=(0, 255), # Standard Wert: default_value=128, # Ausrichtung 'h' oder 'v': orientation='h', # Events bei Nutzung: enable_events=True, key="-REGLER-")], # Alle Ausgaben landen hier: [sg.Input(key="-AUSGABE-", disabled=True)], [sg.Button("Beenden", key="-BEENDEN-")] ] window = sg.Window("Minimalbeispiel", layout, size=(500, 450)) while True: event, values = window.read() # Die beiden folgenden Zeilen auskommentieren (# entfernen) # um events und values zu sehen: # print("event:", event) # print("values:", values) if event == sg.WIN_CLOSED or event == "-BEENDEN-": break if event == "-UEBERTRAGEN-": # So kommt ihr an die Werte heran: text_eingabe = values["-EINGABE-"] # So kommt ihr an die Elemente heran: window["-AUSGABE-"].update(text_eingabe) if event == "-TEST-": window["-AUSGABE-"].update("Testknopf gedrückt!") if event == "-AUSWAHL-": nachricht = values["-AUSWAHL-"] + " ausgewählt!" window["-AUSGABE-"].update(nachricht) if event == "-REGLER-": nachricht = "Regler: " + str(values["-REGLER-"]) window["-AUSGABE-"].update(nachricht) window.close()
2.5 Farbwähler
import PySimpleGUI as sg sg.set_options(font=("Courier", 30)) layout = [[sg.Slider(range=(0, 255), default_value=255, orientation="h", key="-RED-")], [sg.Slider(range=(0, 255), default_value=0, orientation="h", key="-GREEN-")], [sg.Slider(range=(0, 255), default_value=0, orientation="h", key="-BLUE-")], [sg.Button("Beenden", key="-QUIT-")] ] window = sg.Window("Farbmixer", layout) def rgb_to_hex(r, g, b): return "#{:02x}{:02x}{:02x}".format(r, g, b) while(True): event, values = window.read(timeout=100) if event == sg.WIN_CLOSED or event == "-QUIT-": break red = int(values["-RED-"]) green = int(values["-GREEN-"]) blue = int(values["-BLUE-"]) color = rgb_to_hex(red, green, blue) window["-QUIT-"].update(button_color=('white', color)) window.close()
2.6 Farbwähler, kommentiert
import PySimpleGUI as sg sg.set_options(font=("Courier", 30)) layout = [[sg.Slider(range=(0, 255), orientation="h", key="-RED-")], [sg.Slider(range=(0, 255), orientation="h", key="-GREEN-")], [sg.Slider(range=(0, 255), orientation="h", key="-BLUE-")], [sg.Button("Beenden", key="-QUIT-")] ] window = sg.Window("Farbmixer", layout) # Diese Funktion wandelt drei Werte für rot, grün und blau # in den ensprechenden Hex String um: def rgb_to_hex(r, g, b): return "#{:02x}{:02x}{:02x}".format(r, g, b) while(True): # timeout=100 sorgt dafür, dass die values 10 mal # pro Sekunde ausgelesen werden, anstatt auf eine # Eingabe zu warten: event, values = window.read(timeout=100) if event == sg.WIN_CLOSED or event == "-QUIT-": break # Die Werte der Slider sind float, also Dezimalzahlen. # Sie müssen noch in ganze Zahlen (int) umgewandelt werden. # Das erledigt die Funktion int(): red = int(values["-RED-"]) green = int(values["-GREEN-"]) blue = int(values["-BLUE-"]) # Wir nutzen die oben definierte Funktion, um den hex-Wert zu erhalten: color = rgb_to_hex(red, green, blue) # Wir schnappen uns den Quit-Button per window["-QUIT-"] # und ändern die Farbe mit .update(button_color=(...)): window["-QUIT-"].update(button_color=('white', color)) window.close()
3. Projekt Bildbearbeitung
3.1 Bild laden und anzeigen
import PySimpleGUI as sg import cv2 layout = [ [sg.Image(key="-IMAGE-")], [sg.Button("Bild laden"), sg.Button("Beenden")] ] window = sg.Window("Bild laden und anzeigen", layout) while True: event, values = window.read() if event == sg.WINDOW_CLOSED or event == "Beenden": break if event == "Bild laden": filename = sg.popup_get_file("Bild laden", no_window=True) if filename: image = cv2.imread(filename) image_bytes = cv2.imencode('.png', image)[1].tobytes() window["-IMAGE-"].update(data=image_bytes) window.close()
3.2 Bild laden und anzeigen, kommentiert
import PySimpleGUI as sg import cv2 layout = [ [sg.Image(key="-IMAGE-")], [sg.Button("Bild laden"), sg.Button("Beenden")] ] window = sg.Window("Bild laden und anzeigen", layout) while True: event, values = window.read() if event == sg.WINDOW_CLOSED or event == "Beenden": break if event == "Bild laden": # popup_get_file öffnet ein Filedialog-Fenster zur Auswahl # einer Bilddatei. # Der Rückgabewert ist der Pfad zur Datei! filename = sg.popup_get_file("Bild laden", no_window=True) # Wenn es geklappt hat (also filename nicht None ist) ... if filename: # wird das Bild geladen... image = cv2.imread(filename) # und zur Darstellung konvertiert... image_bytes = cv2.imencode('.png', image)[1].tobytes() # und im GUI-Element -Image- angezeigt window["-IMAGE-"].update(data=image_bytes) window.close()
3.4 Kachel ausschneiden und Farbkanäle einzeln anzeigen
import PySimpleGUI as sg import cv2 import numpy as np sg.set_options(font=("Courier", 30)) layout = [ [sg.Image(key="-IMAGE-")], [sg.Button("Bild laden"), sg.Button("Beenden")] ] window = sg.Window("Bild laden und anzeigen", layout) # NEU: Wir verlagern das umwandeln und anzeigen des Bildes # in eine Funktion: def show_image(image): image_bytes = cv2.imencode('.png', image)[1].tobytes() window["-IMAGE-"].update(data=image_bytes) while True: event, values = window.read() if event == sg.WINDOW_CLOSED or event == "Beenden": break if event == "Bild laden": filename = sg.popup_get_file("Bild laden", no_window=True) if filename: image = cv2.imread(filename) kachel = image[200:400, 200:400] kachel_b = kachel[:,:,0] kachel_g = kachel[:,:,1] kachel_r = kachel[:,:,2] image = np.zeros((200, 600, 3)) image[:,0:200,0] = kachel_b image[:,200:400,1] = kachel_g image[:,400:600,2] = kachel_r show_image(image) window.close()