Datenerfassung nach Login

Fragen zu Tkinter.
Antworten
Flair87
User
Beiträge: 4
Registriert: Sonntag 16. Februar 2025, 15:19

Hallo zusammen,
Ich benötige euren Rat, Tipps vielleicht auch die ein oder andere Erklärung zu tkinter und erstellen von Codes objektbasierend.

Meine Projektvorstellung:

Programm startet mit Loginscreen
Fenster mit Entry & Anmelde / Abmelde Button.
Dieses Fenster sollte jederzeit von der Hauptseite aufrufbar sein um sich manuell per button click auszuloggen.


Das Hauptfenster soll unterscheiden,
Ob sich ein Admin oder ein User eingeloggt hat und dementsprechend die Möglichkeit geben verschiedene Parameter einzutragen oder Buttons zu betätigen. Im ausgeloggten Zustand soll das Programm laufen, aber die Eingaben sperren.

Beispiel:
Der Admin, kann die Bezeichnung der Maschine und die Betriebsstunden ändern.
Der User, sieht die Bezeichnung der Maschine und die Betriebsstunden nicht.

Im Hauptfenster soll der Name des eingeloggten und
5 Buttons angezeigt werden.
Über die Buttons möchte ich eine Zeitmessung von verschiedenen Zuständen aufzeichnen.

Beispiel:
Button1 = Anlage läuft
Button2 = Anlage in Wartung
Button3 = Stillstand
usw.

Logt sich User1 ein und klickt auf Button1
Soll die Zeitmessung starten.
Logt sich der nächste User ein und klickt auf Button2, möchte ich die erste Zeitmessung beenden und zum analysieren abspeichern.
Es startet dann wieder eine Zeitmessung usw.

Ich möchte also die Zeiten per Knopfdruck auswerten, wie lange die Anlage lief
und am besten auch das Datum wann der Status geändert wurde und von welchem User.

Optional: Automatisches Logout nach beliebiger Zeit, Anmeldung per RFID


Ich hoffe ich konnte meine Vorstellungen entsprechend beschreiben.

Ich tu mich momentan schon schwer einen Status vernünftig aus ein Loginscreen zubekommen und dementsprechend den mainloop() auszuführen.
Bsp. Wenn User = admin
Dann erzeugen einen Button
Wenn User = Benutzer
Dann erzeugen ein gelbes Label
Wenn User = ausgeloggt
Erzeuge ein rotes Label

Wie würdet Ihr das ganze am besten aufbauen ?
Müssen die Logindaten über Toplevel() laufen.

Mein Verständnis Problem liegt derzeit darin, den mainloop bzw das Hauptfenster anzupassen

Lieben Gruß
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Du beschreibst das ja schon richtig, das Hauptfenster ist das Hauptfenster. Wenn Du noch zusätzlich ein Login-Fenster oder ein Admin-Fenster brauchst, dann generiert man die mit Toplevel.
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Flair87: Ein Abmeldebutton im Login-Fenster macht keinen Sinn. Abmelden würde man sich besser über das Hauptfenster, was dann zur Folge haben sollte, dass der Modale mAnmelde-Dialog angezeigt wird.

Für Dialoge gibt es mit `tkinter.simpledialog.Dialog` eine Basisklasse von der man ableiten kann.

Zum Rechnen mit Zeitpunken und Zeitdauern gibt es was im `datetime`-Modul in der Standardbibliothek. Du solltest darauf achten Objekte zu verwenden die ”aware” sind, also wissen um welche Zeitzone es sich bei ihren Werten handelt. Sonst gibt es Probleme bei der Umstellung zwischen Sommerzeit und Winterzeit (in beide Richtungen). Zum speichern von Zeitstempeln wäre es sinnvoll UTC als Zone zu verwenden.

GUIs erstellt man in der Regel einmal am Anfang. Also nicht ein Label je nach Zustand, sondern *ein* Label, und die Farbe von diesem einen Label wird dann je nach Zustand geändert.

Man sollte die Programmlogik von der GUI sauber trennen, und ich würde empfehlen die Programmlogik zuerst zu schreiben und zu testen, und dann die GUI da drauf zu setzen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Flair87
User
Beiträge: 4
Registriert: Sonntag 16. Februar 2025, 15:19

Vielen Dank schonmal für die ersten Tipps,


Ich habe hier mal mit meinen halbwissen einen code zusammen gebastelt, der die verschiedenen Zeiten erfasst, wenn ein Status verändert wurde und ein Eingabe des gleichen Status anfängt.

Fragt besser nicht wie, aber das ganze scheint doch zu laufen. Das Passwort ist auf 1 gesetzt

Code: Alles auswählen

import time
import datetime as dt

#setup
status = 0

def statusabfrage (eingabe):
	fehler = 1
	while fehler == 1:
		global status, start_status1, start_status2, start_status3
		try:
			if eingabe == 1:
				print ('Status: Produktion')
				start_status1 =  dt.datetime.now()
				print (start_status1)
				fehler = 0
				status = 1
			elif eingabe == 2:
				print ('Status: Störung')
				start_status2 = dt.datetime.now()
				print(start_status2)
				fehler = 0
				status = 2
			elif eingabe == 3:
				print ('Status3')
				start_status3 = dt.datetime.now()
				print(start_status3)
				fehler = 0
				status = 3
			else:
				raise
		except:
			print ('falsche Eingabe')
			eingabe = int(input())
			
#Starte Programm			
while True:
	print ('Login:')
	loginname = input()
	print ('Hallo', loginname, 'Bitte Passwort eingeben')
	password = input()
	key = password
	while key == '1':
		print ('Bitte Status eintragen:')
		eingabe = int(input())
		if status == 0:
			print ("Starte Programm")
			statusabfrage(eingabe)
		elif status == eingabe:
			print ('gleicher Status, keine neue Zeitmessung')
		else:
			print ("Stop Zeitmessung", status)
			if status == 1:
				end_status1 = dt.datetime.now()
				print (end_status1)
				run_status1 = end_status1 - start_status1
				print ('Laufzeit Produktion:', run_status1)
			elif status == 2:
				end_status2 = dt.datetime.now()
				print(end_status2)
				run_status2 = end_status2 - start_status2
				print ('Laufzeit Störung', run_status2)
			elif status == 3:
				end_status3 = dt.datetime.now()
				print(end_status3)
				run_status3 = end_status3 - start_status3
				print ('Laufzeit Status 3', run_status3)
				
				
			statusabfrage(eingabe)
	else:
		print('falsches passwort')
Ich würde mich über eure Hilfe und Ratschläge sehr freuen und lese mich desweiteren hier fleißig durch das Forum und Tutorials.

Lieben Gruß
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Eingerückt wird immer mit 4 Leerzeichen pro Ebene, bei Tabs kommt es zu sehr auf die Editoreinstellungen an, ob der Code noch lesbar ist oder nicht.
`global` hat in einem sauberen Programm nichts verloren. Alles was eine Funktion braucht, bekommt sie über ihre Argumente, Ergebnisse werden per `return` zurückgegeben.
Nackte `except`s darf man nicht verwenden, weil das wirklich alle Exceptions abfängt, auch viele Programmierfehler. Exceptions sollten immer so konkret wie nötig sein und nur den Block umfassen, in dem auch wirklich eine Exception auftreten kann.
Für Flags gibt es True und False, statt 1 und 0. Aber Flags braucht man eh selten, weil man Schleifen auch einfach per `break` oder hier `return` verlassen kann.
Variablen sollten nicht durchnummeriert werden, sondern sprechende Namen bekommen. Für die selben Dinge kann man auch den selben Namen verwenden.
Die Funktion könnte so aussehen:

Code: Alles auswählen

def statusabfrage(eingabe):
    while True:
        if eingabe == 1:
            print("Status: Produktion")
            start_status = dt.datetime.now()
            print(start_status)
            return 1, start_status
        elif eingabe == 2:
            print("Status: Störung")
            start_status = dt.datetime.now()
            print(start_status)
            return 2, start_status
        elif eingabe == 3:
            print("Status3")
            start_status = dt.datetime.now()
            print(start_status)
            return 3, start_status
        else:
            print("falsche Eingabe")
            eingabe = int(input())
Jetzt fällt auf, dass im Prinzip in jedem if-Block der selbe Code steht. Das versucht man durch passende Datenstrukturen zu verhindern:

Code: Alles auswählen

STATUS_TEXTS = {
    1: "Status: Produktion",
    2: "Status: Störung",
    3: "Status3"
}

def statusabfrage(eingabe):
    while True:
        try:
            status_text = STATUS_TEXTS[eingabe]
        except KeyError:
            print("falsche Eingabe")
            eingabe = int(input())
        else:
            print(status_text)
            return eingabe, dt.datetime.now()
Das Hauptprogramm steht üblicherweise in einer Funktion, die `main` genannt wird, das verhindert effektiv, dass doch irgendwo aus Versehen globale Variablen benutzt werden.
Warum nennst Du `password` in `key` um? Da sich `key` innerhalb der while-Schleife nicht mehr ändert, hast Du eine verkappte Endlosschleife mit einem if kombiniert. Besser also explizit if und while True schreiben, damit das dem Leser sofort klar wird, was eigentlich gemeint ist.
Nun ist mir der Programmablauf etwas wirr. Es wird zwar keine neue Zeit aufgenommen, wenn sich der Status nicht ändert, trägt man aber eine falsche Zahl für Status ein, und geht dann wieder zurück, findet doch ein Reset statt. Das ist wahrscheinlich nicht gewollt, durch die Trennung zwischen Vergleich und Neueingabe in zwei unterschiedliche Funktionen wird das aber nicht sofort klar.
Deshalb sollte eine Funktion immer genau eine Aufgabe haben. Also entweder den neuen Status abfragen, oder die neue Zeit eintragen.

Alles in allem könnte das dann so aussehen:

Code: Alles auswählen

from getpass import getpass
import datetime as dt

STATUS_TEXTS = {
    1: "Produktion",
    2: "Störung",
    3: "3"
}

def statusabfrage():
    print("Bitte Status eintragen:")
    while True:
        try:
            eingabe = int(input())
            status_text = STATUS_TEXTS[eingabe]
        except (KeyError, ValueError):
            print("falsche Eingabe")
        else:
            print("Status:", status_text)
            return eingabe

def login():
    while True:
        print("Login:")
        loginname = input()
        print("Hallo", loginname, "Bitte Passwort eingeben")
        password = getpass()
        if password == "1":
            return
        else:
            print("Falsches Passwort.")

def main():
    login()
    status = 0
    start_time = None
    print("Starte Programm")
    while True:
        new_status = statusabfrage()
        if status == new_status:
            print("gleicher Status, keine neue Zeitmessung")
        else:
            if status != 0:
                print("Stop Zeitmessung", status)
                end_time = dt.datetime.now()
                print(end_time)
                run_time = end_time - start_time
                print(f"Laufzeit {STATUS_TEXTS[status]}:", run_time)
            status = new_status
            start_time = dt.datetime.now()

if __name__ == "__main__":
    main()
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Flair87: Als ergänzender Hinweis: GUI-Programmierung funktioniert vom Ablauf her so ziemlich komplett anders als das was bisher hier auf der Konsole mit `print()` und `input()` gemacht wurde. Hier liegt die Kontrolle/Reihenfolge des Programmablaufs komplett in der Hand des Programmierers in selbstgeschriebenen Schleifen die den Ablauf bestimmen. Bei GUI-Programmierung setzt man eine GUI auf und gibt dann die Kontrolle an die Hauptschleife des GUI-Rahmenwerks und der Benutzer bestimmt durch seine Interaktion mit der GUI was wann aufgerufen wird.

Das erfordert in der Regel, und so auch hier, dass man sich Zustand über Aufrufe hinweg merken muss, und das wiederum erfordert objektorientierte Programmierung (OOP), also das man eigene Klassen schreiben können muss.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Flair87
User
Beiträge: 4
Registriert: Sonntag 16. Februar 2025, 15:19

Wahnsinn, was ich jetzt hier schon lernen. Danke euch, dafür ❣️ Wahnsinn wie gut ein Code am Ende aussehen kann, wenn Profis drüber schauen.

Ich habe natürlich mich auch bereits mit tkinter beschäftigt und sicherlich auch hier den ein oder anderen "Klops" rausgehauen 😆

@blackjack du sprichst da genau was an, GUI ist da nochmal ne ganz andere Sache. Das war auch der Grund, weshalb ich an diesen Code erstmal nicht weiter lernen wollte

@Sirius Vielen Dank für deine Mühe, Wahnsinn danke dir. Das mit dem reset beim verlassen war mir nicht bewusst und ist so natürlich nicht gewollt. Die Zeit soll beim ausloggen weiter aufgenommen werden.

Ich habe mich mit diesen Code am Ende nicht mehr so sehr mit beschäftigt und hatte den Fokus tkinter zu lernen. Hier habe ich festgestellt, dass hier doch alles etwas anders läuft.

Mein Ziel wäre hier noch das anbinden einer Datenbank, um die Daten auswerten zu können,die Loginfunktion soll halbwegs laufen und das ganze soll etwas vernünftiger aussehen vom Design.

Das ist mein erstes Projekt in diese Richtung, bitte verzeiht mir meine Anfängerfehler.
Ich bin euch wirklich sehr dankbar, wenn ihr mir meine Fehler auftischt und neue Anregungen gebt.

Ich benutze wahrscheinlich auch hier wieder viel zu viel unnötige global Variablen und Funktionen

Warum legen alle so viel Wert darauf sie zu verhindern ?

Code: Alles auswählen

from tkinter import *
import tkinter as tk
import time
import datetime as dt

global status
status = 0
index=0

#***************Funktion*************
#Vergleich des Status - Berechne die Laufzeit
def statusabfrage():
	global start_status1, start_status2, start_status3
	if status ==1:
		stop_status1 = dt.datetime.now()
		run_status1 = stop_status1 - start_status1
		text_entryEnde.set(run_status1)
	elif status ==2:
		stop_status2 = dt.datetime.now()
		run_status2 = stop_status2 - start_status2
		text_entryEnde.set(run_status2)
	elif status ==3:
		stop_status3 = dt.datetime.now()
		run_status3 = stop_status3 - start_status3
		text_entryEnde.set(run_status3)

		
# Button Aktionen - Prüfung auf Wiederholten Tastenklick - setze Startzeit		
def time_stat1():
	global status,start_status1,start_status2,start_status3
	if status == 1:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status1 =  dt.datetime.now()
		text_entryDaten.set(start_status1)
		text_statusLabel.set('Status: Produktion')
		statusabfrage()
		status = 1
		
def time_stat2():
	global status,start_status1,start_status2,start_status3
	if status == 2:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status2 = dt.datetime.now()
		text_entryDaten.set(start_status2)
		text_statusLabel.set('Status: Störung')
		statusabfrage()
		status = 2
		
def time_stat3():
	global status,start_status1,start_status2,start_status3
	if status == 3:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status3 = dt.datetime.now()
		text_entryDaten.set(start_status3)
		text_statusLabel.set('Status: Beispiel 3')
		statusabfrage()
		status = 3
	
#erstelle Buttons
def create_button():
	global status
	# Login Button
	bn_login= tk.Button(tkFenster, text="Login", command=create_window)
	bn_login.grid(row=13, column=1)
	# Status Button
	bn1 = tk.Button(tkFenster, text="Produktion", command=time_stat1)
	bn1.grid(row=11, column=0)
	bn1.config(foreground = "white" )
	bn1.config(background = "blue")
	bn2 = tk.Button(tkFenster, text="Störung",command=time_stat2)
	bn2.grid(row=11, column=1)
	bn2.config(foreground = "white" )
	bn2.config(background = "blue")
	bn3 = tk.Button(tkFenster, text="Beispiel 3",command=time_stat3)
	bn3.grid(row=11, column=2)
	bn3.config(foreground = "white" )
	bn3.config(background = "blue")
	bn4 = tk.Button(tkFenster, text="Beispiel 4")
	bn4.grid(row=12, column=0)
	bn4.config(foreground = "white" )
	bn4.config(background = "blue")
	bn5 = tk.Button(tkFenster, text="Beispiel 5")
	bn5.grid(row=12, column=1)
	bn5.config(foreground = "white" )
	bn5.config(background = "blue")
	bn6 = tk.Button(tkFenster, text="Beispiel 6")
	bn6.grid(row=12, column=2)
	bn6.config(foreground = "white" )
	bn6.config(background = "blue")
	
#erstelle Loginfenster
def create_window():
    window = Toplevel()
    window.title('Login')
    window.geometry('900x580')
    global user, password
    #Benutzername Eingabefeld
    user = Entry(window, text='', width = 20)
    user.grid(row=0, column=1)
    #Passwort Eingabefeld
    password = Entry(window, text='', show='*')
    password.grid(row=1, column=1)
    #Label als Ausgabefeld/Bestätigung
    entry_Ausgabe.set('')
    ausgabe = Label(master=window,textvariable = entry_Ausgabe)
    ausgabe.grid(row=2, column=1)
    #Anmelde Button
    buttonLogin = Button(window, text = 'Anmelden', command=login_click)
    buttonLogin.grid(row=3, column=1)
    #Abmelde Button
    buttonLogout = Button(window, text = 'Abmelden', command=window.destroy)
    buttonLogout.grid(row=4, column=1)
    
#Aktion Login Button
#to-do: Zugriff auf Hauptfenster Buttons, Admin Ebene / User Ebene per Datenbank
def login_click ():
		# Übernahme der Daten
		#global eingabe_username
		eingabe_username = str(user.get())
		eingabe_pw = str(password.get())
		# Anzeige Anmeldeprozess
		if eingabe_username == '1' and eingabe_pw == '1':
			entry_Ausgabe.set('Erfolgreich angemeldet, Hallo' + eingabe_username)
			#Übertrag auf tkFenster Label
			labelAngemeldet.config(text='Angemeldet:' + eingabe_username)
		else:
			entry_Ausgabe.set('falscher Benutzername oder falsches Passwort')
			labelAngemeldet.config(text='Ausgeloggt')

#Aktion Logout Button _ Warum schließt das Fenster nicht bei destroy ?
def logout_click():
	window.destroy
	labelAngemeldet.config(text='Ausgeloggt')	

#setup
 #to-Do:Die Bezeichnung der Anlage soll der Admin ändern dürfen
anlage= 'MA 700t'


#erstelle Hauptfenster
tkFenster = Tk()
tkFenster.title('Datenerfassung')

entry_Ausgabe=StringVar()
text_statusLabel=StringVar()

#tkFenster.geometry('558x295')

# Label Angemeldet
labelAngemeldet = Label(master=tkFenster, text = 'Abgemeldet')
labelAngemeldet.grid(row=0, column=2)
# Label Überschrift Datenerfassung
labelÜberschrift = Label(master=tkFenster, bg='#265E80', fg= 'white', text='Datenerfassung')
labelÜberschrift.grid(row=1, column=1)
# Label Anlage
labelAnlage = Label(master=tkFenster,width=15, bg='#FFFFFF', fg='black', borderwidth=10, relief="groove", text='Anlage: ' + anlage)
labelAnlage.grid(row=2, column=0)


# Entry für Passwort
text_entryLogin = StringVar()
text_entryLogin.set('Passwort')
# Label für aktiven Status
labelStatus = Label(master=tkFenster,width = 15, bg='#FFFFFF', fg='black', borderwidth=10, relief="groove", textvariable=text_statusLabel)
labelStatus.grid(row=3, column=0)
# Label für Startzeit
labelStartzeit = Label(master=tkFenster, bg='#D5E88F', text='Startzeit:')
labelStartzeit.grid(row=4, column=1)
# Entry für Startzeit
text_entryDaten=StringVar()
entryDaten = Entry(master=tkFenster, bg='white', textvariable=text_entryDaten)
text_entryDaten.set('Start')
entryDaten.grid(row=5, column=1)
# Label für Endzeit
labelEndzeit = Label(master=tkFenster, bg='gray', text='Endzeit')
labelEndzeit.grid(row=6, column=1)
# Entry für Endzeit
text_entryEnde=StringVar()
entryEnde = Entry(master=tkFenster, bg='white', textvariable=text_entryEnde)
text_entryEnde.set('Ende')
entryEnde.grid(row=7, column=1)

text_statusLabel.set('Start')
create_button()


while True:
	# Aktivierung des Fensters
	tkFenster.mainloop()from tkinter import *
import tkinter as tk
import time
import datetime as dt

global status
status = 0
index=0

#***************Funktion*************
#Vergleich des Status - Berechne die Laufzeit
def statusabfrage():
	global start_status1, start_status2, start_status3
	if status ==1:
		stop_status1 = dt.datetime.now()
		run_status1 = stop_status1 - start_status1
		text_entryEnde.set(run_status1)
	elif status ==2:
		stop_status2 = dt.datetime.now()
		run_status2 = stop_status2 - start_status2
		text_entryEnde.set(run_status2)
	elif status ==3:
		stop_status3 = dt.datetime.now()
		run_status3 = stop_status3 - start_status3
		text_entryEnde.set(run_status3)

		
# Button Aktionen - Prüfung auf Wiederholten Tastenklick - setze Startzeit		
def time_stat1():
	global status,start_status1,start_status2,start_status3
	if status == 1:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status1 =  dt.datetime.now()
		text_entryDaten.set(start_status1)
		text_statusLabel.set('Status: Produktion')
		statusabfrage()
		status = 1
		
def time_stat2():
	global status,start_status1,start_status2,start_status3
	if status == 2:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status2 = dt.datetime.now()
		text_entryDaten.set(start_status2)
		text_statusLabel.set('Status: Störung')
		statusabfrage()
		status = 2
		
def time_stat3():
	global status,start_status1,start_status2,start_status3
	if status == 3:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status3 = dt.datetime.now()
		text_entryDaten.set(start_status3)
		text_statusLabel.set('Status: Beispiel 3')
		statusabfrage()
		status = 3
	
#erstelle Buttons
def create_button():
	global status
	# Login Button
	bn_login= tk.Button(tkFenster, text="Login", command=create_window)
	bn_login.grid(row=13, column=1)
	# Status Button
	bn1 = tk.Button(tkFenster, text="Produktion", command=time_stat1)
	bn1.grid(row=11, column=0)
	bn1.config(foreground = "white" )
	bn1.config(background = "blue")
	bn2 = tk.Button(tkFenster, text="Störung",command=time_stat2)
	bn2.grid(row=11, column=1)
	bn2.config(foreground = "white" )
	bn2.config(background = "blue")
	bn3 = tk.Button(tkFenster, text="Beispiel 3",command=time_stat3)
	bn3.grid(row=11, column=2)
	bn3.config(foreground = "white" )
	bn3.config(background = "blue")
	bn4 = tk.Button(tkFenster, text="Beispiel 4")
	bn4.grid(row=12, column=0)
	bn4.config(foreground = "white" )
	bn4.config(background = "blue")
	bn5 = tk.Button(tkFenster, text="Beispiel 5")
	bn5.grid(row=12, column=1)
	bn5.config(foreground = "white" )
	bn5.config(background = "blue")
	bn6 = tk.Button(tkFenster, text="Beispiel 6")
	bn6.grid(row=12, column=2)
	bn6.config(foreground = "white" )
	bn6.config(background = "blue")
	
#erstelle Loginfenster
def create_window():
    window = Toplevel()
    window.title('Login')
    window.geometry('900x580')
    global user, password
    #Benutzername Eingabefeld
    user = Entry(window, text='', width = 20)
    user.grid(row=0, column=1)
    #Passwort Eingabefeld
    password = Entry(window, text='', show='*')
    password.grid(row=1, column=1)
    #Label als Ausgabefeld/Bestätigung
    entry_Ausgabe.set('')
    ausgabe = Label(master=window,textvariable = entry_Ausgabe)
    ausgabe.grid(row=2, column=1)
    #Anmelde Button
    buttonLogin = Button(window, text = 'Anmelden', command=login_click)
    buttonLogin.grid(row=3, column=1)
    #Abmelde Button
    buttonLogout = Button(window, text = 'Abmelden', command=window.destroy)
    buttonLogout.grid(row=4, column=1)
    
#Aktion Login Button
#to-do: Zugriff auf Hauptfenster Buttons, Admin Ebene / User Ebene per Datenbank
def login_click ():
		# Übernahme der Daten
		#global eingabe_username
		eingabe_username = str(user.get())
		eingabe_pw = str(password.get())
		# Anzeige Anmeldeprozess
		if eingabe_username == '1' and eingabe_pw == '1':
			entry_Ausgabe.set('Erfolgreich angemeldet, Hallo' + eingabe_username)
			#Übertrag auf tkFenster Label
			labelAngemeldet.config(text='Angemeldet:' + eingabe_username)
		else:
			entry_Ausgabe.set('falscher Benutzername oder falsches Passwort')
			labelAngemeldet.config(text='Ausgeloggt')

#Aktion Logout Button _ Warum schließt das Fenster nicht bei destroy ?
def logout_click():
	window.destroy
	labelAngemeldet.config(text='Ausgeloggt')	

#setup
 #to-Do:Die Bezeichnung der Anlage soll der Admin ändern dürfen
anlage= 'MA 700t'


#erstelle Hauptfenster
tkFenster = Tk()
tkFenster.title('Datenerfassung')

entry_Ausgabe=StringVar()
text_statusLabel=StringVar()

#tkFenster.geometry('558x295')

# Label Angemeldet
labelAngemeldet = Label(master=tkFenster, text = 'Abgemeldet')
labelAngemeldet.grid(row=0, column=2)
# Label Überschrift Datenerfassung
labelÜberschrift = Label(master=tkFenster, bg='#265E80', fg= 'white', text='Datenerfassung')
labelÜberschrift.grid(row=1, column=1)
# Label Anlage
labelAnlage = Label(master=tkFenster,width=15, bg='#FFFFFF', fg='black', borderwidth=10, relief="groove", text='Anlage: ' + anlage)
labelAnlage.grid(row=2, column=0)


# Entry für Passwort
text_entryLogin = StringVar()
text_entryLogin.set('Passwort')
# Label für aktiven Status
labelStatus = Label(master=tkFenster,width = 15, bg='#FFFFFF', fg='black', borderwidth=10, relief="groove", textvariable=text_statusLabel)
labelStatus.grid(row=3, column=0)
# Label für Startzeit
labelStartzeit = Label(master=tkFenster, bg='#D5E88F', text='Startzeit:')
labelStartzeit.grid(row=4, column=1)
# Entry für Startzeit
text_entryDaten=StringVar()
entryDaten = Entry(master=tkFenster, bg='white', textvariable=text_entryDaten)
text_entryDaten.set('Start')
entryDaten.grid(row=5, column=1)
# Label für Endzeit
labelEndzeit = Label(master=tkFenster, bg='gray', text='Endzeit')
labelEndzeit.grid(row=6, column=1)
# Entry für Endzeit
text_entryEnde=StringVar()
entryEnde = Entry(master=tkFenster, bg='white', textvariable=text_entryEnde)
text_entryEnde.set('Ende')
entryEnde.grid(row=7, column=1)

text_statusLabel.set('Start')
create_button()


while True:
	# Aktivierung des Fensters
	tkFenster.mainloop()
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Flair87: Globale Variablen machen Programme schwerer zu verstehen, schwerer zu testen, und damit fehleranfälliger und schlechter wartbar. Man hat dann nicht einzelne Funktionen die man isoliert verstehen und testen kann, sondern Code der auf undurchsichtige Weise zusammenhängt, wo man *alles* auf einmal kennen und verstehen muss.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Flair87
User
Beiträge: 4
Registriert: Sonntag 16. Februar 2025, 15:19

Hey Freunde, ich muss euch um Hilfe bitten.

Ich komme einfach nicht mehr weiter und habe irgendwo einen Denkfehler und würde gerne verstehen, wie sich tkinter genau verhält

Die Zeiten werden jetzt gut erfasst und in einer Datenbank abgelegt.

Jetzt hänge ich an meiner Login Vorstellung fest und bekomme es nicht umgesetzt.

Meine Idee:

Admin eingeloggt = Ebene 2 (Vollzugriff)
User eingeloggt = Ebene 1 (Teilzugriff, erstelle Buttons)
Ausgeloggt = Ebene 0 (Buttons verstecken, nur Ansicht des Mainfenster)

Code: Alles auswählen

from tkinter import *
import tkinter as tk
import time
import datetime as dt
import sqlite3

verbindung = sqlite3.connect("datenbank.db")
zeiger = verbindung.cursor()

sql_anweisung = """
CREATE TABLE IF NOT EXISTS anlage (
user TEXT, 
projekt TEXT,
aktion VARCHAR(30), 
startzeit DATE,
endzeit DATE,
laufzeit DATE
);"""
zeiger.execute(sql_anweisung)

user   = "Admin"
projekt = "FA 250135"
aktion = "Programm gestartet"
startzeit = dt.datetime.now()
endzeit = "0"
laufzeit = "0"

zeiger.execute("""
                INSERT INTO anlage 
                       VALUES (?,?,?,?,?,?)
               """, 
              (user, projekt, aktion, startzeit, endzeit, laufzeit)
              )

#verbindung.commit()
verbindung.close()
ebene = 1
status=0
#***************Funktion*************
#Vergleich des Status - Berechne die Laufzeit
def schreibeDatenbank():
	global status, startzeit, laufzeit, endzeit, aktion
	verbindung = sqlite3.connect("datenbank.db")
	zeiger = verbindung.cursor()
	zeiger.execute("""
                INSERT INTO anlage
                       VALUES (?,?,?,?,?,?)
               """, 
              (user, projekt, aktion, startzeit, endzeit, laufzeit)
              )
	verbindung.commit()
	verbindung.close()


def statusabfrage():
	global status, startzeit, laufzeit, endzeit, aktion,start_status1, start_status2, start_status3
	#endzeit = dt.datetime.now()
	if status==1:
		endzeit = dt.datetime.now()
		startzeit = start_status1
		laufzeit = str(endzeit - start_status1)
		aktion='Produktion'
	elif status ==2:
		endzeit = dt.datetime.now()
		startzeit = start_status2
		laufzeit = str(endzeit - start_status2)
		aktion = 'Rüsten Aufbauen'
	elif status ==3:
		endzeit = dt.datetime.now()
		startzeit = start_status3
		laufzeit = str(endzeit - start_status3)
		aktion = 'Rüsten Abbauen'
	
	text_entryEnde.set(laufzeit)
	schreibeDatenbank()

		
# Button Aktionen - Prüfung auf Wiederholten Tastenklick - setze Startzeit		
def time_stat1():
	global status, start_status1, start_status2,start_status3
	if status== 1:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status1 =  dt.datetime.now()
		text_entryDaten.set(start_status1)
		text_statusLabel.set('Status: Produktion\n -aktiv-')
		statusabfrage()
		status= 1
		
def time_stat2():
	global status,start_status1,start_status2,start_status3
	if status == 2:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status2 = dt.datetime.now()
		text_entryDaten.set(start_status2)
		text_statusLabel.set('Status: Rüsten\nAufbauen')
		statusabfrage()
		status = 2
		
def time_stat3():
	global status,start_status1,start_status2,start_status3
	if status == 3:
		text_entryDaten.set('gleiche Zeitmessung')
	else:
		start_status3 = dt.datetime.now()
		text_entryDaten.set(start_status3)
		text_statusLabel.set('Status: Rüsten\nAbbauen')
		statusabfrage()
		status = 3
	
#erstelle Buttons
def create_button():
	
	# Status Button
	bn1 = tk.Button(tkFenster, text="Produktion",width = 15,height = 2, command=time_stat1)
	bn1.grid(row=12, column=1,pady = '20', padx = '10')
	bn1.config(foreground = "white" )
	bn1.config(background = "blue")
	bn2 = tk.Button(tkFenster, text= "Rüsten\n -Werkzeug aufbauen-",width = 15,height = 2,command=time_stat2)
	bn2.grid(row=13, column=0,pady = '20', padx = '10')
	bn2.config(foreground = "white" )
	bn2.config(background = "blue")
	bn3 = tk.Button(tkFenster, text="Rüsten\n - Werkzeug Abbauen-",width = 15,height = 2,command=time_stat3)
	bn3.grid(row=13, column=1,pady = '20', padx = '10')
	bn3.config(foreground = "white" )
	bn3.config(background = "blue")
	bn4 = tk.Button(tkFenster, text="Störung\n -Werkzeug- ",width = 15,height = 2)
	bn4.grid(row=14, column=0,pady = '20', padx = '10')
	bn4.config(foreground = "white" )
	bn4.config(background = "blue")
	bn5 = tk.Button(tkFenster, text="Störung\n -Qualität- ",width = 15,height = 2,)
	bn5.grid(row=14, column=1,pady = '20', padx = '10')
	bn5.config(foreground = "white" )
	bn5.config(background = "blue")
	bn6 = tk.Button(tkFenster, text="Störung\n -Rohstoff- ",width = 15,height = 2,)
	bn6.grid(row=14, column=2,pady = '20', padx = '10')
	bn6.config(foreground = "white" )
	bn6.config(background = "blue")
	bn7 = tk.Button(tkFenster, text="Störung\n -Maschine- ",width = 15,height = 2,)
	bn7.grid(row=14, column=3,pady = '20', padx = '10')
	bn7.config(foreground = "white" )
	bn7.config(background = "blue")
	bn8 = tk.Button(tkFenster, text="Störung\n -Maschine- ",width = 15,height = 2,)
	bn8.grid(row=15, column=0,pady = '20', padx = '10')
	bn8.config(foreground = "white" )
	bn8.config(background = "blue")
	
#erstelle Loginfenster
def create_window():
    window = Toplevel()
    window.title('Login')
    window.geometry('900x580')
    global userEntry, password
    #Benutzername Eingabefeld
    userEntry = Entry(window, text='', width = 20)
    userEntry.grid(row=0, column=1)
    #Passwort Eingabefeld
    password = Entry(window, text='', show='*')
    password.grid(row=1, column=1)
    #Label als Ausgabefeld/Bestätigung
    entry_Ausgabe.set('')
    ausgabe = Label(master=window,textvariable = entry_Ausgabe)
    ausgabe.grid(row=2, column=1)
    #Anmelde Button
    buttonLogin = Button(window, text = 'Anmelden', command=login_click)
    buttonLogin.grid(row=3, column=1)
    #Abmelde Button
    buttonLogout = Button(window, text = 'Abmelden', command=window.destroy)
    buttonLogout.grid(row=4, column=1)
    
#Aktion Login Button
#to-do: Zugriff auf Hauptfenster Buttons, Admin Ebene / User Ebene per Datenbank
def login_click ():
	global userEntry, password, user, ebene
	# Übernahme der Daten
	#global eingabe_username
	eingabe_username = str(userEntry.get())
	#eingabe_pw = str(password.get())
	# Anzeige Anmeldeprozess
	checkPasswort = "1234"
	eingabe_pw = str(password.get())
	
	if eingabe_pw == checkPasswort:
			entry_Ausgabe.set('Erfolgreich angemeldet, Hallo' + eingabe_username)
			#Übertrag auf tkFenster Label
			labelAngemeldet.config(text='Angemeldet:' + eingabe_username)
			user = str(userEntry.get())
			ebene = 1
			
			#entry_Ausgabe.set('3x falscher Benutzername oder falsches Passwort')
	else:
		entry_Ausgabe.set('falscher Benutzername oder falsches Passwort')
		labelAngemeldet.config(text='Ausgeloggt')
		
		#i = 0 #Hier läuft die 3er Überwachung nicht
		
#Aktion Logout Button _ Warum schließt das Fenster nicht bei destroy ?
def logout_click():
	window.destroy
	labelAngemeldet.config(text='Ausgeloggt')	

#setup
#to-Do:Die Bezeichnung der Anlage soll der Admin ändern dürfen
anlage= 'MA 700t'


#erstelle Hauptfenster
tkFenster = Tk()
tkFenster.title('Datenerfassung')

entry_Ausgabe=StringVar()
text_statusLabel=StringVar()

#tkFenster.geometry('55x25')

# Label Angemeldet
labelAngemeldet = Label(master=tkFenster, text = 'Abgemeldet')
labelAngemeldet.grid(row=0, column=2)
# Label Überschrift Datenerfassung
labelÜberschrift = Label(master=tkFenster, bg='#265E80', fg= 'white',width = '60', text='Datenerfassung')
labelÜberschrift.grid(row=1,columnspan=6)
# Label Anlage
labelAnlage = Label(master=tkFenster,width=15, bg='#FFFFFF', fg='black', borderwidth=10, relief="groove", text='Anlage: ' + anlage)
labelAnlage.grid(row=2, column=0)


# Entry für Passwort
text_entryLogin = StringVar()
text_entryLogin.set('Passwort')#!!?
# Label für aktiven Status
labelStatus = Label(master=tkFenster,width = 15, bg='#FFFFFF', fg='black', borderwidth=10, height=2,relief="groove", textvariable=text_statusLabel)
labelStatus.grid(row=3, column=0)
# Label für Startzeit
labelStartzeit = Label(master=tkFenster, bg='#D5E88F', text='Startzeit:')
labelStartzeit.grid(row=4, column=1)
# Entry für Startzeit
text_entryDaten=StringVar()
entryDaten = Entry(master=tkFenster, bg='white', textvariable=text_entryDaten)
text_entryDaten.set('Start')
entryDaten.grid(row=5, column=1)
# Label für Endzeit
labelEndzeit = Label(master=tkFenster, bg='gray', text='Endzeit')
labelEndzeit.grid(row=6, column=1)
# Entry für Endzeit
text_entryEnde=StringVar()
entryEnde = Entry(master=tkFenster, bg='white', textvariable=text_entryEnde)
text_entryEnde.set('Ende')
entryEnde.grid(row=7, column=1)

text_statusLabel.set('Start')
# Login Button
bn_login= tk.Button(tkFenster, text="Login", command=create_window)
bn_login.grid(row=18, column=1)
if ebene ==1:
	create_button()


if __name__ == "__main__":
	# Aktivierung des Fensters
	tkFenster.mainloop()

Verzeiht mit diese unübersichtliche und schlechte Programmierung.

Ich vermute ich verstehe die tkinter mainloop() Funktion nicht richtig ?

Ich habe oben im Code die variable "ebene" erstmal auf 1 gesetzt, damit ihr die Buttons seht

Ich versuche die variable über login_click zu erfahren und darüber das tkFenster zu steuern.

Die variable ebene bleibt aber immer auf den selben Status.

Die Buttons sind nur die ersten drei aktiv programmiert per command
Antworten