Projekterstellung mit GUI

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Habe mal weiter rum gespielt:

Code: Alles auswählen

from tkinter import *
import schuetzeanlegen

db = schuetzeanlegen.connect()

root = Tk()
frame1 = Frame(root)
frame1.pack()

frame2 = Frame(root)
frame2.pack()

frame3 = Frame(root)
frame3.pack(side = BOTTOM)


w = schuetzeanlegen.get_users2(db)

Label(frame1, text = "Schiessbuch", font = "Arial 14 bold").pack()
Label(frame1, text = "Bitte wähle deine ID aus: ").pack()

for row in w:
          
	Label(frame2,
			text= (row["ID"], row["UName"], row["UVorname"]),
			fg = "red",
			font = "Arial").pack(fill=X,pady=10)


e1 = Entry(frame3)
e1.pack(padx=5, pady=20, side=LEFT)

Buttonchoice= Button(frame3, text ="OK")
Buttonchoice.pack(padx=5, pady=20, side=LEFT)

root.title("Schiessbuch")
root.geometry("500x500")
root.mainloop()
Was ja dann erstmal heißt, dass ich alles was als print() rauskommt aus schuetzeanlegen.py in Returns umgebaut werden muss.

Dann muss ich irgendwie die Programmlogik in tkinter bringen.

in diesem Beispiel hier müsse der User jetzt seine Zahl eingeben und dann muss irgendwie auf die nächste Abfrage gesprungen werden.

Im Endausbau soll aber die Userauswahl per RFID funktionieren.


EDIT:

Kleines Update. DIe Abfragen in Module verschoben:

Code: Alles auswählen

#!/usr/bin/python3

from tkinter import *
import schuetzeanlegen


def show_users(db, frame):
	w = schuetzeanlegen.get_users2(db)
	for row in w:
		Label(frame,
				text= (row["ID"], row["UName"], row["UVorname"]),
				fg = "red",
				font = "Arial").pack(fill=X,pady=10)

def entry_box(frame):
	e1 = Entry(frame)
	e1.pack(padx=5, pady=20, side=LEFT)

	Buttonchoice= Button(frame, text ="OK")
	Buttonchoice.pack(padx=5, pady=20, side=LEFT)


def main():

	db = schuetzeanlegen.connect()

	root = Tk()
	frame1 = Frame(root)
	frame1.pack()

	frame2 = Frame(root)
	frame2.pack()

	frame3 = Frame(root)
	frame3.pack(side = BOTTOM)
	
	Label(frame1, text = "Schiessbuch", font = "Arial 14 bold").pack()
	Label(frame1, text = "Bitte wähle deine ID aus: ").pack()


	show_users(db, frame2)
	
	entry_box(frame3)

	

	root.title("Schiessbuch")
	root.geometry("500x500")
	root.mainloop()

if __name__ == '__main__':
    main()

Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Sternchenimporte sind böse. Tkinter wird üblicherweise per `import tkinter as tk` eingebunden und alle Namen per tk.xyz referenziert.
Auch hier solltest Du alles, was jetzt auf oberster Ebene steht, in eine `main`-Funktion packen.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Habe schon ein Teil in Main gepackt,
Poste morgen mal den aktuellen Code.

Bin da grade am schauen wegen der Rückgabe eines Entrys.

Will aber noch eine Prüfung und eingabe für die Standaufsicht machen.

Weil man nur schiessen darf wenn eine Standaufsicht da ist.
Da mag ich noch was vorschalten.


EDIT: das ist auch erstmal nur gebastelt, um auch den Zusammenhang zu verstehen.
Daher die ganzen Fragen.
Google, weiss auch schon gleich was ich will😂😂
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Guten Morgen,

das ist der aktuelle Stand:

Code: Alles auswählen

#!/usr/bin/python3

from tkinter import *
import schuetzeanlegen


def show_users(db, frame):
	w = schuetzeanlegen.get_users2(db)
	for row in w:
		Label(frame,
				text= (row["ID"], row["UName"], row["UVorname"]),
				fg = "red",
				font = "Arial").pack(fill=X,pady=10)



def entry_box(frame):
	e1 = Entry(frame)
	e1.pack(padx=5, pady=20, side=LEFT)
	print(e1.get())
	

def entry_button(frame):
	Buttonchoice= Button(frame, text ="OK")
	Buttonchoice.pack(padx=5, pady=20, side=LEFT)


def main():

	db = schuetzeanlegen.connect()

	root = Tk()
	frame1 = Frame(root)
	frame1.pack()

	frame2 = Frame(root)
	frame2.pack()

	frame3 = Frame(root)
	frame3.pack(side = BOTTOM)
	
	Label(frame1, text = "Schiessbuch", font = "Arial 14 bold").pack()
	Label(frame1, text = "Bitte wähle deine ID aus: ").pack()


	show_users(db, frame2)
	
	entry_box(frame3)
	entry_button(frame3)
	

	root.title("Schiessbuch")
	root.geometry("500x500")
	root.mainloop()

if __name__ == '__main__':
    main()

matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Wie müsste ich vorgehen um die Rückmeldungen zuverarbeiten?

Sprich den Entry verarbeiten und dann damit auf die nächste Abfrage kommen. Dann soll sich ja auch der INhalt des UI ändern für die darauf folgende Abfrage.
Benutzeravatar
__blackjack__
User
Beiträge: 13061
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.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Ach du liebes Lieschen :-)

Das geht als weiter in die Tiefe :-)

Das heißt ich muss mir Klassen bauen, die meine Werte behalten oder Klassen bauen die diese Abfragen steuern?
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

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()

Hallo,

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?
Benutzeravatar
__blackjack__
User
Beiträge: 13061
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.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

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.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

So ganz geschnalt habe ich es noch nicht.

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()
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du mal genau hingeschaut, was du da geschrieben hast? Wie du mehrere Argumente an eine Funktion uebergeben musst, und was du stattdessen tust?
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

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?

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()

matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

war zu schnell!

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()

Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

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.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

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?

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()

Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Das `master`, das in buttons_bottom zu viel ist, fehlt in `show_users`. Oder eben besser auch als Methode von `MainWindow` definieren, wo auch `db` hingehört.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Ich weiss immer noch nicht, welches Master du meinst. Sorry für die Begriffsstutzigkeit. Weil wenn ich das Master aus

Code: Alles auswählen

def buttons_bottom(self, master):
nehme geht es nicht

und wenn ich das master aus

Code: Alles auswählen

self.frame3 = tk.Frame(self.master)
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

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()

Benutzeravatar
__blackjack__
User
Beiträge: 13061
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. :-)
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Ich hoffe nun alles ausgemerzt zuhaben.

das ist aber nun der Fehler, wenn ich master aus den Funktionen lasse
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
Wo lasse ich nun am besten das self weg? Das kam für mich jetzt nicht so rüber.

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()


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.
Antworten