Fiiiinaaale, Ohoooo!
Heute machen wird unseren Software-Manager fertig. Das ist keine große Sachen, deswegen bekommt Ihr zur streckung des Artikel noch mal ein paar Hintergrund-Infos von mir!
Zum zeichnen des Fensters/Programms/GUIs haben wir Tkinter benutzt. Es ist sehr flexibel und gibt für jedes Widget zig Stellschrauben die eine Optische veränderung hervorrufen. Den Hintergrund rot, blau oder gelb zu machen sind da nur Taschenspielertricks. Das haben wir übrigens nur zu besseren Übersicht gemacht, sonst wäre alles einfach grau gewesen.
Der Vorteil ist aber auch Tkinters Nachteil. Es macht sein eigenes Ding. Das Modul ist nicht an GTK oder Qt gekoppelt. Somit fällt schonmal ein automatischer Dark-Mode flach und es passt sich nicht perfekt in die Gnome-Design-Philosophie ein. Dafür gibt es aber python-gtk und python-qt. Ich habe mit Tkinter angefangen und müsste mir eigentlich mal selbst in den Hinter GTK lernen, das nervige ist das wie bei jedem Python-Modul eine eigene Syntax erlernt werden muss. Also lesen lesen lesen!
Also auf geht's
Das ist unser Code vom letzen mal:
from tkinter import *
import os
# Zeichnet das Fensters
main = Tk()
main.title('Software Manager')
main.geometry("600x600")
def up_action():
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt update -y && sleep 5 && exit ; exec bash"'% wid)
def upg_action():
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt upgrade -y && sleep 5 && exit ; exec bash"'% wid)
def install_action():
get_entry = enrty_box.get()
inst_plus_entry = f"install {get_entry}"
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt {inst_plus_entry} -y && sleep 5 && exit; exec bash"'% wid)
def remove_action():
get_entry = enrty_box.get()
remove_plus_entry = f"remove {get_entry}"
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt {remove_plus_entry} -y && sleep 5 && exit; exec bash"'% wid)
button_frame = Frame(main,background="red")
button_frame.pack(fill="both",expand=True)
update_button = Button(button_frame, text="Update",command=up_action)
update_button.pack(side=LEFT)
upgrade_button = Button(button_frame, text="Upgrade",command=upg_action)
upgrade_button.pack(side=LEFT)
installer_frame = Frame(main,background="yellow")
installer_frame.pack(fill="both",expand=True)
apt_label = Label(installer_frame,text="apt")
apt_label.pack(side=LEFT)
install_button = Button(installer_frame, text="install",command=install_action)
install_button.pack(side=LEFT)
remove_button = Button(installer_frame, text="remove",command=remove_action)
remove_button.pack(side=LEFT)
enrty_box = Entry(installer_frame)
enrty_box.pack(side=LEFT)
terminal_frame = Frame(main,background="blue")
terminal_frame.pack(fill="both",expand=True)
wid = terminal_frame.winfo_id()
# Startet das Fenser
main.mainloop()
Alles anzeigen
Wir nehmen uns die Widget vor!
main.geometry("600x600")>600x300
Das Fenster kann ruhig etwas kleiner sein.
button_frame
Vorher:
Nachher:
button_frame = LabelFrame(main,text="System Update",padx=5,pady=5)
button_frame.pack(fill="x",pady=10,padx=10)
Aus unserem Frame ist ein LabelFrame geworden. Er hat jetzt eine Rahmung und der Titel wird angezeigt. den background haben wir entfernt. mit pady und x geben wir an das alles was sich in dem Frame befindet an jeder seiner Seiten einen gewissen Abstand halten soll.
fill füllt nun nur noch die Horizontale. pady und x in einem .pack() geben den Abstand zu Widgets nach Außen an.
Die beiden Buttons ergänzen wir um
.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
Das ist im Grunde die Standart-Behandelung für alle unsere Widgets.
terminal_frame.pack(fill="both",expand=True) wird zu terminal_frame.pack(fill="both",expand=True,pady=10,padx=10)
Am Ende bekommen wir schöne Grüße aus der Windows2000-Zeit
from tkinter import *
import os
# Zeichnet das Fensters
main = Tk()
main.title('Software Manager')
main.geometry("600x300")
def up_action():
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt update -y && sleep 5 && exit ; exec bash"'% wid)
def upg_action():
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt upgrade -y && sleep 5 && exit ; exec bash"'% wid)
def install_action():
get_entry = enrty_box.get()
inst_plus_entry = f"install " + get_entry
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt {inst_plus_entry} -y && sleep 5 && exit; exec bash"'% wid)
def remove_action():
get_entry = enrty_box.get()
remove_plus_entry = f"remove " + get_entry
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt {remove_plus_entry} -y && sleep 5 && exit; exec bash"'% wid)
#Schritt 8:button_frame > LabelFrame; padx,y=15 |.pack(side=LEFT,fill="x",expand=True)
button_frame = LabelFrame(main,text="System Update",padx=5,pady=5)
button_frame.pack(fill="x",pady=10,padx=10)
update_button = Button(button_frame, text="Update",command=up_action)
update_button.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
upgrade_button = Button(button_frame, text="Upgrade",command=upg_action)
upgrade_button.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
#Schritt 9:installer_frame > LabelFrame; padx,y=15 |.pack(side=LEFT,fill="x",expand=True)
installer_frame = LabelFrame(main,text="APT Installer/Remover",padx=5,pady=5)
installer_frame.pack(fill="x",pady=10,padx=10)
#Schritt 9:installer_frame > LabelFrame; padx,y=15 |.pack(side=LEFT,fill="x",expand=True)
install_button = Button(installer_frame, text="install",command=install_action)
install_button.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
remove_button = Button(installer_frame, text="remove",command=remove_action)
remove_button.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
enrty_box = Entry(installer_frame)
enrty_box.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
#Schritt 9:installer_frame > LabelFrame; padx,y=15 |.pack(side=LEFT,fill="x",expand=True)
terminal_frame = Frame(main)
terminal_frame.pack(fill="both",expand=True,pady=10,padx=10)
wid = terminal_frame.winfo_id()
# Startet das Fenser
main.mainloop()
Alles anzeigen
Noch "schöner"
Weil tkinter von Haus aus sehr modern wirkt *hust*, haben sich ein paar Leute dran gesetzt den Look noch moderner zu machen! In tkinter (python3-tk) ist mittlerweile auch das ttk-Modul integriert. Das steht für Themed-Tkinter.
Wunder oh wunder, man muss sich hier fast wieder eine neue Syntax drauf schaffen. So schlimm ist es aber nicht.
Nachteil: Es sieht alles etwas moderner aus, die Einstellmöglichkeiten sind jedoch geringer. Es ist ja eben schon ge-themed!
Was haben wir hier?
Viel muss nicht gemacht werden! Wir importieren from tkinter import ttk
Fügen die Variable styler hinzu:
Guckt den Code genau an. Die Widgets sind jetzt ttk.Widgets (ttk.Button).
Ich musste noch einen Frame hinzufügen in dem alles liegt (main_frame), somit müssen unsere LabelFrames alle in den main_frame gepackt werden. Hat den Hintergrund das... der Hintergrund vonmain = Tk() sich nicht an die ttk-Farbgebung anpasst.
padx und y füntioniert nicht mehr IN Widgets aber AUßEN und wird IN Widget durch padding= für x und y ersetzt.
So läuft das halt wenn man Etwas auf etwas Anders drauf bastelt.
from tkinter import *
import tkinter as tk
from tkinter import ttk
import os
#ttk Version + main_frame
# Zeichnet das Fensters
main = tk.Tk()
main.title('Software Manager')
main.geometry("600x300")
styler = ttk.Style()
styler.theme_use('clam')
def up_action():
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt update -y && sleep 5 && exit ; exec bash"'% wid)
def upg_action():
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt upgrade -y && sleep 5 && exit ; exec bash"'% wid)
def install_action():
get_entry = enrty_box.get()
inst_plus_entry = f"install " + get_entry
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt {inst_plus_entry} -y && sleep 5 && exit; exec bash"'% wid)
def remove_action():
get_entry = enrty_box.get()
remove_plus_entry = f"remove " + get_entry
os.popen(f'xterm -into %d -bg Grey11 -geometry 1000x50 -e "pkexec apt {remove_plus_entry} -y && sleep 5 && exit; exec bash"'% wid)
#Schritt 8:button_frame > LabelFrame; padx,y=15 |.pack(side=LEFT,fill="x",expand=True)
main_frame = ttk.Frame(main)
main_frame.pack(fill="both", expand=True)
button_frame = ttk.LabelFrame(main_frame,text="System Update",padding=5)
button_frame.pack(fill="x",pady=10,padx=10)
update_button = ttk.Button(button_frame, text="Update",command=up_action)
update_button.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
upgrade_button = ttk.Button(button_frame, text="Upgrade",command=upg_action)
upgrade_button.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
#Schritt 9:installer_frame > LabelFrame; padx,y=15 |.pack(side=LEFT,fill="x",expand=True)
installer_frame = ttk.LabelFrame(main_frame,text="APT Installer/Remover",padding=5)
installer_frame.pack(fill="x",pady=10,padx=10)
#Schritt 9:installer_frame > LabelFrame; padx,y=15 |.pack(side=LEFT,fill="x",expand=True)
install_button = ttk.Button(installer_frame, text="install",command=install_action)
install_button.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
remove_button = ttk.Button(installer_frame, text="remove",command=remove_action)
remove_button.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
enrty_box = ttk.Entry(installer_frame)
enrty_box.pack(side=LEFT,fill="x",expand=True,pady=10,padx=10)
#Schritt 9:installer_frame > LabelFrame; padx,y=15 |.pack(side=LEFT,fill="x",expand=True)
terminal_frame = ttk.Frame(main_frame)
terminal_frame.pack(fill="both",expand=True,pady=10,padx=10)
wid = terminal_frame.winfo_id()
# Startet das Fenser
main.mainloop()
Alles anzeigen
Und... .
Natürlich hat sich noch Jemand gedacht: "Das geht noch schöner"!. Ja, das ist mein Ernst! Hierfür müssen wir aber ein Paket installieren, und zwar tcl-ttkthemes. https://ttkthemes.readthedocs.io/en/latest/themes.html
Was hier für Entspannung sorgt ist, dass es ttk-Zusatz ist. Wir können also mit der ttk-Syntax arbeiten.
Ersetzt einfach clam durch adapta, yaru, breeze oder wie die alle heißen. Ich mag yaru aber es gibt leider kein yaru-dark
FERTIG!
Ganz ehrlich. So ein Tutorial gibt es nirgendwo und deswegen habe ich es auch gemacht. Man kann das alles im Internet finden aber nicht Zentral an einem Platz. Als ich angefangen habe, musste ich mir einen ähnlichen Code aus 50 man-pages, StackOverflow-Artikel und Videos zusammenschustern.
Empfehlung
[Youtube]Codemy - Learn Python Playlist (25 Videos)
[Youtube]Codemy - Learn Tkinter Playlist (200 Videos)
KEINE Werbung, aber guter Rat.
Ich lese gerne IT-Fachliteratur, natürlich auch über Python. Hier gibt es sehr gute, aber auch, nun ja, unvorteilhaft geschriebene Bücher.
Man hangelt sich strikt an einen Plan lang, und zwar: Fraktura! Das Problem ist, dass ich am Ende nur ganz explizit weiß, was man für ein Verwaltungsprogramm eines Autohauses braucht.
Das Zauberwort ist Transferleistung. Ein Anfänger kann das nicht, und nach dem Lesen ist er absolut kein Experte.
Dies ist ein dicker Wälzer und bringt von vorne bis hinten alles mit, was standardmäßig in Python implementiert ist. Richtig gut für Anfänger und zum Nachschlagen.
Mein absoluter Favorit, wenn es um Tkinter geht, aber nichts für Anfänger. Hier wird vorausgesetzt, dass ihr wisst, wie man mit Klassen (Class) arbeitet.
Das ist Next-Level-Sh@! und sollte niemals von einem Anfänger gekauft werden. Hier wird vermittelt, wie man Tkinter auf einem Profi-Level nutzt. Leider ist es zusätzlich verwirrend geschrieben, so dass man teilweise nicht weiß, in welche Datei oder Zeile man den Code schreiben soll.
Ich besitze alle Bücher und habe sie von vorne bis hinten gelesen und durchgearbeitet. Sie sind vollgekleistert mit Post-its, falls ich mal etwas nachschlagen muss.
Wie schon erwähnt, Transferleistung ist hier ALLES!
Ich hab mir überlegt, die Python-Bastelstunde weiter zu führen. Ich hab noch einen Raupen-Roboter auf Raspberry Pi-Basis in der Schublade und der will dringen weiterentwickelt werden. Das hat dann aber keinen Tutorial-Charakter. Ich werde das Ding komplett von Grund auf bauen und programmieren. Also eher ein Erfahrungsbericht/Wöchentliches Update...?! Irgendwas muss man ja im Winter machen...
Kommentare 7