Projekterstellung mit GUI
- __blackjack__
- User
- Beiträge: 14133
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@matze1708: Für jede nicht-triviale GUI braucht man objektorientierte Programmierung (OOP), weil man sich ja über Aufrufe hinweg Zustand merken muss. Du müsstest Dich also mal mit Klassen auseinander setzen.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Code: Alles auswählen
import tkinter as tk
class MainWindow:
def __init__(self, master):
self.master = master
self.master.geometry("500x500")
self.master.title("Schiessbuch")
self.frame1 = tk.Frame(self.master)
self.Label1 = tk.Label(self.frame1, text = "Schiessbuch", font = "Arial 14 bold")
self.Label1.pack()
self.Label2 = tk.Label(self.frame1, text = "Bitte wähle deine ID aus: ")
self.Label2.pack()
self.frame1.pack()
self.frame2 = tk.Frame(self.master)
self.e1 = tk.Entry(self.frame2)
self.e1.pack(padx=5, pady=20)
self.Buttonchoice= tk.Button(self.frame2, text ="OK")
self.Buttonchoice.pack(padx=5, pady=20)
self.frame2.pack()
def main():
root = tk.Tk()
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
ich habe mal etwas probiert und einen kleinen Teil in MainWindow verschoben.
Frage
ist das schon zuviel in MainWIndows?
Wie kann ich das pack() anordnen? side=LEFT etc bringt er als Fehler raus, er würde es nicht kennen
wie rufe ich jetzt hier die nächsten Dinge auf?
- __blackjack__
- User
- Beiträge: 14133
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@matze1708: `LEFT` ist ja in der Tat auch nirgends definiert. Das ist aus dem `tkinter`-Modul, wie `Tk`, `Button`, …
Du musst halt bei der Schaltfläche ein `command`-Argument angeben, dass dann aufgerufen wird wenn die Schaltfläche geklickt wird. Die darf dann kurz etwas machen, und dann zur GUI-Hauptschleife zurück kehren.
Du musst halt bei der Schaltfläche ein `command`-Argument angeben, dass dann aufgerufen wird wenn die Schaltfläche geklickt wird. Die darf dann kurz etwas machen, und dann zur GUI-Hauptschleife zurück kehren.
“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Es ist nicht nötig, alles an Attribute zu binden. Die Label werden ja sonst nicht mehr gebraucht, da ist sogar gar keine Variable nötig.
`e1` ist ein ganz schlechter Variablenname, wie auch alle anderen mit Nummern.
`Buttonchoice` hält sich nicht an die Konvention und wird wahrscheinlich auch nicht mehr gebrauct.
LEFT kommt auch aus Tkinter -> tk.LEFT
Um das = bei Keyword-Argumente setzt man keine Leerzeichen.
`e1` ist ein ganz schlechter Variablenname, wie auch alle anderen mit Nummern.
`Buttonchoice` hält sich nicht an die Konvention und wird wahrscheinlich auch nicht mehr gebrauct.
LEFT kommt auch aus Tkinter -> tk.LEFT
Um das = bei Keyword-Argumente setzt man keine Leerzeichen.
So ganz geschnalt habe ich es noch nicht.
Jetzt meint er das Syntax nicht stimmt bei side=tk.BOTTOM :-O
Jetzt meint er das Syntax nicht stimmt bei side=tk.BOTTOM :-O
Code: Alles auswählen
import tkinter as tk
class MainWindow:
def __init__(self, master):
self.master = master
self.master.geometry("500x500")
self.master.title("Schiessbuch")
self.frame1 = tk.Frame(self.master)
self.Label1 = tk.Label(self.frame1, text = "Schiessbuch", font = "Arial 14 bold")
self.Label1.pack()
self.Label2 = tk.Label(self.frame1, text = "Bitte wähle deine ID aus: ")
self.Label2.pack()
self.frame1.pack()
self.frame2 = tk.Frame(self.master)
self.enty_userid = tk.Entry(self.frame2)
self.enty_userid.pack(padx=5, pady=20 side=tk.BOTTOM)
self.button_choice_userid = tk.Button(self.frame2, text ="OK")
self.button_choice_userid.pack(padx=5, pady=20 side=tk.BOTTOM)
self.frame2.pack()
def main():
root = tk.Tk()
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
Habe mein fehlendes Komma gefunden! :-O
Habe es auch erstmal einigermaßen erfolgreich hinbekommen.
Nun will ich aber die Überschrift und die button_BOTTOM Gedöns, in eine Funktion schreiben, innerhalb der Klasse.
Wie rufe ich das auf? Oder spreche ich die Klasse anders an?
Habe es auch erstmal einigermaßen erfolgreich hinbekommen.
Nun will ich aber die Überschrift und die button_BOTTOM Gedöns, in eine Funktion schreiben, innerhalb der Klasse.
Wie rufe ich das auf? Oder spreche ich die Klasse anders an?
Code: Alles auswählen
import tkinter as tk
import funktion
class MainWindow:
def __init__(self, master):
self.master = master
self.master.geometry("1000x1000")
self.master.title("Schießbuch")
self.frame1 = tk.Frame(self.master)
self.Label1 = tk.Label(self.frame1, text = "Schießbuch", font = "Arial 14 bold")
self.Label1.pack()
self.frame1.pack(side=tk.TOP)
ueberschrift(self)
buttons_bottom(self)
def ueberschrift(self):
self.frame2 =tk.Frame(self.master)
self.Label2 = tk.Label(self.frame1, text = "Bitte wähle deine ID aus: ")
self.Label2.pack(padx=5, pady=20)
self.frame2.pack(side=tk.BOTTOM)
def buttons_bottom(self):
self.frame3 = tk.Frame(self.master)
self.enty_userid = tk.Entry(self.frame3)
self.enty_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.button_choice_userid = tk.Button(self.frame3, text ="OK")
self.button_choice_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.frame3.pack(side=tk.BOTTOM)
def main():
root = tk.Tk()
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
war zu schnell!
Habe es. Muss es auch mit self aufrufen und den master noch übergeben!
Habe es. Muss es auch mit self aufrufen und den master noch übergeben!
Code: Alles auswählen
import tkinter as tk
import funktion
class MainWindow:
def __init__(self, master):
self.master = master
self.master.geometry("1000x1000")
self.master.title("Schießbuch")
self.frame1 = tk.Frame(self.master)
self.Label1 = tk.Label(self.frame1, text = "Schießbuch", font = "Arial 14 bold")
self.Label1.pack()
self.frame1.pack(side=tk.TOP)
self.ueberschrift(self.master)
self.buttons_bottom(self.master)
def ueberschrift(self, master):
self.frame2 =tk.Frame(self.master)
self.Label2 = tk.Label(self.frame1, text = "Bitte wähle deine ID aus: ")
self.Label2.pack(padx=5, pady=20)
self.frame2.pack(side=tk.BOTTOM)
def buttons_bottom(self, master):
self.frame3 = tk.Frame(self.master)
self.enty_userid = tk.Entry(self.frame3)
self.enty_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.button_choice_userid = tk.Button(self.frame3, text ="OK")
self.button_choice_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.frame3.pack(side=tk.BOTTOM)
def main():
root = tk.Tk()
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
Das `master`-Argument ist unnötig, weil unbenutzt. Ein Modul das `funktion` heißt, ist zu generisch. Wenn Du keinen passenden Namen findest heißt das wohl, dass Du was in ein Modul gepackt hast, was nicht zusammengehört.
Tippfehler sind auch Fehlerquellen: enty_userid.
Tippfehler sind auch Fehlerquellen: enty_userid.
Das Master Element, kann ich nicht rausnehmen. Da sagt er mir, das 1 Argument verfügbar ist aber 2 kommen.
Wie und vorallem wo, rufe ich denn am besten die Show_users auf?
Wie und vorallem wo, rufe ich denn am besten die Show_users auf?
Code: Alles auswählen
import tkinter as tk
import sql_aufrufe
class MainWindow:
def __init__(self, master):
self.master = master
self.master.geometry("1000x1000")
self.master.title("Schießbuch")
self.frame1 = tk.Frame(self.master)
self.Label1 = tk.Label(self.frame1, text = "Schießbuch", font = "Arial 14 bold")
self.Label1.pack()
self.frame1.pack(side=tk.TOP)
self.ueberschrift(self.master)
self.buttons_bottom(self.master)
def ueberschrift(self, master):
self.frame2 =tk.Frame(self.master)
self.Label2 = tk.Label(self.frame1, text = "Bitte wähle deine ID aus: ")
self.Label2.pack(padx=5, pady=20)
self.frame2.pack(side=tk.BOTTOM)
def buttons_bottom(self, master):
self.frame3 = tk.Frame(self.master)
self.enty_userid = tk.Entry(self.frame3)
self.enty_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.button_choice_userid = tk.Button(self.frame3, text ="OK")
self.button_choice_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.frame3.pack(side=tk.BOTTOM)
def show_users(db):
frame4 =tk.Frame()
w = sql_aufrufe.get_users(db)
for row in w:
tk.Label(frame4, text= (row["ID"], row["UName"], row["UVorname"]),
fg = "red",
font = "Arial")
frame4.pack(fill=X,pady=10)
def main():
db = sql_aufrufe.connect()
#show_users(db)
root = tk.Tk()
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
Ich weiss immer noch nicht, welches Master du meinst. Sorry für die Begriffsstutzigkeit. Weil wenn ich das Master aus nehme geht es nicht
und wenn ich das master aus geht es auch nicht.
Verstehe den Zusammenhang noch nicht wirklich.
Sowie ich es jetzt gepostet habe, bekomme ich zumindest mal das was ich gerne haben mag. Ob es praktikabel ist weiß nicht ....
Schon gar nicht wo ich die Antworten aus den eingaben hernehme und wie ich die weiter verwende.
Code: Alles auswählen
def buttons_bottom(self, master):
und wenn ich das master aus
Code: Alles auswählen
self.frame3 = tk.Frame(self.master)
Verstehe den Zusammenhang noch nicht wirklich.
Sowie ich es jetzt gepostet habe, bekomme ich zumindest mal das was ich gerne haben mag. Ob es praktikabel ist weiß nicht ....
Schon gar nicht wo ich die Antworten aus den eingaben hernehme und wie ich die weiter verwende.
Code: Alles auswählen
import tkinter as tk
import sql_aufrufe
class MainWindow:
def __init__(self, master):
db = sql_aufrufe.connect()
self.master = master
self.master.geometry("1000x1000")
self.master.title("Schießbuch")
self.frame1 = tk.Frame(self.master)
self.Label1 = tk.Label(self.frame1, text = "Schießbuch", font = "Arial 14 bold")
self.Label1.pack()
self.frame1.pack(side=tk.TOP)
self.ueberschrift(self.master)
self.buttons_bottom(self.master)
show_users(db, self.master)
def ueberschrift(self, master):
self.frame2 =tk.Frame(self.master)
self.Label2 = tk.Label(self.frame1, text = "Bitte wähle deine ID aus: ")
self.Label2.pack(padx=5, pady=20)
self.frame2.pack(side=tk.BOTTOM)
def buttons_bottom(self, master):
self.frame3 = tk.Frame(self.master)
self.entry_userid = tk.Entry(self.frame3)
self.entry_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.button_choice_userid = tk.Button(self.frame3, text ="OK")
self.button_choice_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.frame3.pack(side=tk.BOTTOM)
def show_users(db, self):
self.frame4 =tk.Frame(self.master)
w = sql_aufrufe.get_users(db)
for row in w:
self.Label_Users = tk.Label(self.frame4, text= (row["ID"], row["UName"], row["UVorname"]),
fg = "red",
font = "Arial")
self.Label_Users.pack(fill=tk.X, pady=10)
self.frame4.pack()
def main():
#show_users(db)
root = tk.Tk()
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
- __blackjack__
- User
- Beiträge: 14133
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@matze1708: Das `master`-Argument aus `ueberschrift()` und `buttons_bottom()` zu nehmen geht sehr wohl. Es wird in den beiden Methoden ja gar nicht benutzt, warum sollte man das dann übergeben müssen?
Die beiden Methodennamen beschreiben übrigens keine Tätigkeiten.
`self` sollte man nur das erste Argument von Methoden nennen. Wirklich kein anderes Argument sollte so heissen, das ist extrem verwirrend. Das dieser Name eine superbesondere Bedeutung hat, macht auch die farbige Syntaxhervorhebung hier (und in den meisten Editoren/IDEs) klar. Hier im Forum wird das sogar wie ein Schlüsselwort eingefärbt.
Namen durchnummerieren ist immer noch keine gute Idee. Und ich glaube es wurde auch schon mal angesprochen das man nicht alles an das Objekt binden muss, sondern nur Werte die auch tatsächlich für den Zustand benötigt werden. Dann erledigt sich das mit der Nummerierung bei einigen Namen mehr oder weniger automatisch.
`w` ist kein guter Name. Ich wüsste nicht mal Ansatzweise wofür das hier eine Abkürzung sein sollte.
Bei `self.Label_Users` sieht man eigentlich schon wegen der Schleife, dass das keinen Sinn macht an ein Objekt gebunden zu werden, denn da wird ja am Ende nur der Wert vom letzten Schleifendurchlauf übrig bleiben.
Der Name entspricht nicht den Namenskonventionen. Es ist ganz schön ermüdend die jedes mal wieder erwähnen zu müssen. Sooo schwer kann das doch nicht sein nahezu alles klein_mit_unterstrichen zu schreiben. Inhaltlich ist der Name auch komisch weil es sich nicht um *mehrere* Labelbenutzer handelt, sondern um *ein* Benutzerlabel, also `user_label`.
Ein `grid()` wäre wahrscheinlich schöner, und man wird Probleme bekommen wenn es dort mehr Benutzer als Platz auf dem Bildschirm gibt. Dann müsste man sich etwas Scrollbares für die Anzeige nehmen. Oder auf was anderes als Tk setzen.
Die beiden Methodennamen beschreiben übrigens keine Tätigkeiten.
`self` sollte man nur das erste Argument von Methoden nennen. Wirklich kein anderes Argument sollte so heissen, das ist extrem verwirrend. Das dieser Name eine superbesondere Bedeutung hat, macht auch die farbige Syntaxhervorhebung hier (und in den meisten Editoren/IDEs) klar. Hier im Forum wird das sogar wie ein Schlüsselwort eingefärbt.
Namen durchnummerieren ist immer noch keine gute Idee. Und ich glaube es wurde auch schon mal angesprochen das man nicht alles an das Objekt binden muss, sondern nur Werte die auch tatsächlich für den Zustand benötigt werden. Dann erledigt sich das mit der Nummerierung bei einigen Namen mehr oder weniger automatisch.
`w` ist kein guter Name. Ich wüsste nicht mal Ansatzweise wofür das hier eine Abkürzung sein sollte.
Bei `self.Label_Users` sieht man eigentlich schon wegen der Schleife, dass das keinen Sinn macht an ein Objekt gebunden zu werden, denn da wird ja am Ende nur der Wert vom letzten Schleifendurchlauf übrig bleiben.
Der Name entspricht nicht den Namenskonventionen. Es ist ganz schön ermüdend die jedes mal wieder erwähnen zu müssen. Sooo schwer kann das doch nicht sein nahezu alles klein_mit_unterstrichen zu schreiben. Inhaltlich ist der Name auch komisch weil es sich nicht um *mehrere* Labelbenutzer handelt, sondern um *ein* Benutzerlabel, also `user_label`.
Ein `grid()` wäre wahrscheinlich schöner, und man wird Probleme bekommen wenn es dort mehr Benutzer als Platz auf dem Bildschirm gibt. Dann müsste man sich etwas Scrollbares für die Anzeige nehmen. Oder auf was anderes als Tk setzen.

“It is easier to change the specification to fit the program than vice versa.” — Alan J. Perlis
Ich hoffe nun alles ausgemerzt zuhaben.
das ist aber nun der Fehler, wenn ich master aus den Funktionen lasse
muss ich sowas wie das Show_users() überhaupt mit self aufrufen?
EDIT:
Ich baue auch gern auf was anderes. Wenn das sinnvoller ist.
Aber es soll später keine User Liste geben, da soll dann der RFID aufruf sein.. Danach kommen nur die kleinen anzeigen, Kaliber, Platz Standaufsicht.
das ist aber nun der Fehler, wenn ich master aus den Funktionen lasse
Wo lasse ich nun am besten das self weg? Das kam für mich jetzt nicht so rüber.Traceback (most recent call last):
File "test2.py", line 61, in <module>
main()
File "test2.py", line 57, in main
app = MainWindow(root)
File "test2.py", line 18, in __init__
self.ueberschrift(self.master)
TypeError: ueberschrift() takes 1 positional argument but 2 were given
muss ich sowas wie das Show_users() überhaupt mit self aufrufen?
Code: Alles auswählen
import tkinter as tk
import sql_aufrufe
class MainWindow:
def __init__(self, master):
db = sql_aufrufe.connect()
self.master = master
self.master.geometry("1000x1000")
self.master.title("Schießbuch")
self.frame1 = tk.Frame(self.master)
self.label1 = tk.Label(self.frame1, text = "Schießbuch", font = "Arial 14 bold")
self.label1.pack()
self.frame1.pack(side=tk.TOP)
self.ueberschrift(self.master)
self.buttons_bottom(self.master)
show_users(db, self.master)
def ueberschrift(self):
self.frame2 =tk.Frame(self.master)
self.label2 = tk.Label(self.frame1, text = "Bitte wähle deine ID aus: ")
self.label2.pack(padx=5, pady=20)
self.frame2.pack(side=tk.BOTTOM)
def buttons_bottom(self):
self.frame3 = tk.Frame(self.master)
self.entry_userid = tk.Entry(self.frame3)
self.entry_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.button_choice_userid = tk.Button(self.frame3, text ="OK")
self.button_choice_userid.pack(padx=5, pady=20, side=tk.LEFT)
self.frame3.pack(side=tk.BOTTOM)
def show_users(db, self):
self.frame4 =tk.Frame(self.master)
users = sql_aufrufe.get_users(db)
for row in users:
self.user_label = tk.Label(self.frame4, text= (row["ID"], row["UName"], row["UVorname"]),
fg = "red",
font = "Arial")
self.user.label.pack(fill=tk.X, pady=10)
self.frame4.pack()
def main():
#show_users(db)
root = tk.Tk()
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
Ich baue auch gern auf was anderes. Wenn das sinnvoller ist.
Aber es soll später keine User Liste geben, da soll dann der RFID aufruf sein.. Danach kommen nur die kleinen anzeigen, Kaliber, Platz Standaufsicht.
Welche von den beiden self.irgendwas in "self.ueberschrift(self.master)" hat denn was mit master zu tun, und koennte darum der erste Kandidat fuer das weglassen sein? Und dann sind das ja auch theoretisch nur 2 Moeglichkeiten (an dieser Stelle.) Das dauert ja nun nicht einen Nachmittag auszuprobieren, welches weg muss.
Bei diesen hier geht es so.
Wenn ich bei den anderen was wegnehme, geht es nicht.
Innerhalb der Funktion, verweist das self.master auf das tk.
aber es war doch noch mehr wo ich self zu viel habe.
EDIT:
Alles was innerhalb der Klasse ist, kann ich nur mit self aufrufen, sonst streikt er.
Wenn ich bei den anderen was wegnehme, geht es nicht.
Innerhalb der Funktion, verweist das self.master auf das tk.
aber es war doch noch mehr wo ich self zu viel habe.
Code: Alles auswählen
self.ueberschrift(self)
self.buttons_bottom(self)
show_users(db, self)
Alles was innerhalb der Klasse ist, kann ich nur mit self aufrufen, sonst streikt er.
Du kannst das nicht erraten. Du musst das schon versuchen zu verstehen, warum eine Methode die so deklariert wird
SO aufgerufen wird:
Und das ein_objekt_mit_meine_methode in deinem Fall self ist, ist voellig unerheblich.
Das ist wirklich ganz grundlegend Python OO. Dafuer gibt es eine Menge an Tutorials da draussen, die einem das erklaeren.
Code: Alles auswählen
def meine_methode(self, ein_argument):
...
Code: Alles auswählen
ein_objekt_mit_meine_methode.meine_methode("DAS ARGUMENT") # KEIN SELF! NIRGENDWO!
Das ist wirklich ganz grundlegend Python OO. Dafuer gibt es eine Menge an Tutorials da draussen, die einem das erklaeren.
Ja. Das ist die entscheidende Eigenschaft einer Methode, dass sie nur in Zusammenhang mit einem dazugehoerigen Objekt aufgerufen werden kann. Du rufst doch auchmatze1708 hat geschrieben: Mittwoch 27. März 2019, 14:52 Alles was innerhalb der Klasse ist, kann ich nur mit self aufrufen, sonst streikt er.
Code: Alles auswählen
root = tk.Tk()
...
root.mainloop()
Also nochmal: alles ganz Grundlegende OO, die du dir raufschaffen musst.
Hallo,
ich muss nochmal eine zwischen Frage stellen,
ich möchte von der Gesamtmenge der Plätze aus get_max_place_number und der Teilmenge get_occupied_place_numbers die freien Plätze bekommen.
Versuche ich das aber wie unten, in eine Liste zuschieben,
Sagt er folgendes:
Was muss ich tun?
Danke und Liebe Grüße
ich muss nochmal eine zwischen Frage stellen,
ich möchte von der Gesamtmenge der Plätze aus get_max_place_number und der Teilmenge get_occupied_place_numbers die freien Plätze bekommen.
Versuche ich das aber wie unten, in eine Liste zuschieben,
Sagt er folgendes:
Jetzt hatte ich versucht diverse Funktionen als list zu formatieren. Das hat es auch nicht gebracht.Traceback (most recent call last):
File "schuetzeanlegen.py", line 273, in <module>
main()
File "schuetzeanlegen.py", line 253, in main
print(get_free_place_list(db, range_id))
File "schuetzeanlegen.py", line 181, in get_free_place_list
for place_number in range(1, max_place_number + 1)
TypeError: can only concatenate list (not "int") to list
Was muss ich tun?
Code: Alles auswählen
def get_occupied_place_numbers(db, range_id):
with closing(db.cursor()) as cursor:
cursor.execute(
'SELECT Platz FROM tbl_Schiesstand'
' WHERE Ende IS NULL AND StandID = %s',
(range_id,)
)
return [row['Platz'] for row in cursor]
def get_max_place_number(db, range_id):
with closing(db.cursor()) as cursor:
cursor.execute("""SELECT PlaetzeMax FROM tbl_Stand WHERE ID =%s """, (range_id,))
return [row['PlaetzeMax'] for row in cursor]
def get_free_place_list(db, range_id):
occupied_place_numbers = set(get_occupied_place_numbers(db, range_id))
max_place_number = get_max_place_number(db, range_id)
free_place_numbers = [
place_number
for place_number in range(1, max_place_number + 1)
if place_number not in occupied_place_numbers]
return free_place_numbers
Danke und Liebe Grüße