Status-Anzeige wird einfach übersprungen(?)

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.
Antworten
fickAdmiral
User
Beiträge: 5
Registriert: Mittwoch 25. November 2020, 21:35

Hallo,

ich versuche grade ein simples login mit tkinter zu realisieren. das ganze ist ein frames aufgelteilt. es gibt drei davon:

1) frame_login:
hier ist das login-formular

2) frame_loader:
nach erfolgreichem login müssen noch weitere daten abgefragt werden über eine REST-API, den fortschritt würde ich gerne in diesem frame anzeigen lassen

3) frame_content:
ist alles fertig geladen, wird dieses frame erzeugt

alles funktioniert soweit.. nur bekomme ich das frame_loader nicht zu sehen.. nachdem ich den loginversuch starte kommt direkt das frame_content(?) +vielleicht kann mir jemand sagen was ich falsch mache?

Code: Alles auswählen

from tkinter import *
from tkinter import ttk
from tkinter import font as tkfont 

import requests
from requests.exceptions import HTTPError
import pymysql 
import pprint
import time
import asyncio  


root = Tk()
root.resizable(False, False)
root.title("MyApp")
root.geometry('600x300')

s = ttk.Style()

# - Vars
canvas_width = 600
canvas_height = 100

API_host = "http://examle.com/api/"

# - MySQL
db = pymysql.connect("11.11.11.12","username","password","dbname")
mySqlCursor = db.cursor()


# ---------------------------------------- FRAME login ----------------------------------------
def create_login():

    root.geometry('600x300')

    # create main-frame
    frame_login_content = ttk.Frame(root, padding=(0,0,0,0))       
    
    # create login-form into main-frame
    login_form = ttk.Frame(frame_login_content, padding=(0,1,1,1))    

    labelframeLogin = ttk.LabelFrame(login_form, text = "Please login: ")
    labelframeLogin.pack(expand="yes", padx=15, pady=15)               

    labelUser = ttk.Label(labelframeLogin, text='Usr:') 
    entryUser = ttk.Entry(labelframeLogin)         
    labelPwd = ttk.Label(labelframeLogin, text='Pwd:')  
    entryPwd = ttk.Entry(labelframeLogin)     
       
    button1 = ttk.Button(login_form, text = "Login", width = 20, command = lambda: doLogin(entryUser.get(), entryPwd.get()))
    button1.pack(padx=10, pady=10)

    # layut - grid
    frame_login_content.grid(column=0, row=0, sticky=(N, S, E, W))
    login_canvas.grid(column=0, row=0, sticky=(E, W))
    login_form.grid(column=0, row=1, sticky=(E, W), padx=10, pady=10)


    labelUser.grid(column=1, row=2, sticky=(E, W), padx=10, pady=3)
    entryUser.grid(column=2, row=2, sticky=(E, W), padx=10, pady=3)
    labelPwd.grid(column=1, row=3, sticky=(E, W), padx=10, pady=3)
    entryPwd.grid(column=2, row=3, sticky=(E, W), padx=10, pady=3)

    # weight elements
    root.columnconfigure(0, weight=1)
    root.rowconfigure(0, weight=1)
    frame_login_content.columnconfigure(0, weight=3)
    frame_login_content.columnconfigure(1, weight=3)
    frame_login_content.columnconfigure(2, weight=3)
    frame_login_content.columnconfigure(3, weight=1)
    frame_login_content.columnconfigure(4, weight=1)
    frame_login_content.rowconfigure(1, weight=1)

    return frame_login_content


# ---------------------------------------- FRAME loader ----------------------------------------
def create_loader(msg): 

    global actualFrame

    actualFrame2 = actualFrame
    actualFrame2.destroy()   

    # create main-frame
    frame_loader_content = ttk.Frame(root, padding=(0,0,0,0))   
    actualFrame = frame_loader_content

    login_title = ttk.Label(frame_loader_content, text = "Bitte warten", anchor="center") 
    login_msg = ttk.Label(frame_loader_content, text = msg, anchor="center", foreground = "#666666")

    frame_loader_content.grid(column=0, row=0, sticky=(N, S, E, W), padx=10, pady=10)
    login_title.grid(column=0, row=0, columnspan=5, sticky=(E, W), padx=10, pady=3)
    login_msg.grid(column=0, row=1, columnspan=5, sticky=(E, W), padx=10, pady=3)

    root.geometry('600x80')

    # weight elements
    root.columnconfigure(0, weight=1)
    root.rowconfigure(0, weight=1)
    frame_loader_content.columnconfigure(0, weight=3)  

    return frame_loader_content

   
# ---------------------------------------- FRAME content ----------------------------------------
def create_content():    

    create_loader("Requestion API")

    # - request API
    p = makeRestCall(API_host, {})

   # - check if request worked
    try:   
        request Check = len(p) 

    except:
        create_loader("ERROR - request-JSON is currupt") 

    else:         
        create_loader("request ok")
        contentFrame = buildContentFrame(p)

        return contentFrame
       

# ---------------------------------------- FUNCTIONS ----------------------------------------
def doLogin(u,p):    

    create_loader('Logging in')

    # - Perform login and check result
    # .....
        
    for x in myresult: 
        if x["USERID"]:
            logInCheck = 1 

    if logInCheck == 1: 
        create_loader("Login successfull")
        create_content()
    else:        
        create_login()



# - call first frame 
actualFrame = create_login()

root.mainloop()
ich habe bereits versucht in die funktion create_loader() ein time.sleep(1) einzubringen aber das verzögert einfach nur die wartezeit vom login bis zur anzeige des content-frame.
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo *Admiral,
wie testest Du deinen Code?
Überprüfe deinen try except Block. Da ist ein Fehler drin.
Vermeide Sternchen Importe. Hier im Forum findest Du die Gründe.
Variablen werden durchwegs klein geschrieben.
Gruss Peter
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@fickAdmiral: Du hast eine falsche Vorstellung davon, wie GUIs funktionieren. GUIs sind eventgesteuert, das heißt, dass es einen mainloop gibt, der für jedes Event das Auftritt einen Callback aufruft, der nur kurz etwas tun darf, und dann wieder zur Mainloop zurückkehrt. Für langlaufende Aufgaben braucht man einen Hintergrundthread.
fickAdmiral
User
Beiträge: 5
Registriert: Mittwoch 25. November 2020, 21:35

peterpy hat geschrieben: Donnerstag 3. Dezember 2020, 08:45 Hallo *Admiral,
wie testest Du deinen Code?
Überprüfe deinen try except Block. Da ist ein Fehler drin.
Vermeide Sternchen Importe. Hier im Forum findest Du die Gründe.
Variablen werden durchwegs klein geschrieben.
Gruss Peter
Hi, danke für die Antwort.
Also ich bin noch weit von unit-testing in python entfernt, wenn du das meinst mit "wie testest Du deinen Code?". Ansonsten teste ich indem ich sehe ob es funktioniert ^^
Ob so oder so, das loader_frame mit einer spezifischen message sollte doch dennoch angezeigt werden(?).
fickAdmiral
User
Beiträge: 5
Registriert: Mittwoch 25. November 2020, 21:35

Sirius3 hat geschrieben: Donnerstag 3. Dezember 2020, 09:37 @fickAdmiral: Du hast eine falsche Vorstellung davon, wie GUIs funktionieren. GUIs sind eventgesteuert, das heißt, dass es einen mainloop gibt, der für jedes Event das Auftritt einen Callback aufruft, der nur kurz etwas tun darf, und dann wieder zur Mainloop zurückkehrt. Für langlaufende Aufgaben braucht man einen Hintergrundthread.
Hi, danke für den Tipp. Ich versuche das mal event-gesteuert umzuschreiben.
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo *Admiral,
Ansonsten teste ich indem ich sehe ob es funktioniert
Da wirst Du aber Zeit mit Fehler suchen verschwenden.
Lass deinen Code zum Testen in Idle laufen, ist doch in Python integriert.
Idle sagt dir auch wo und was für Fehler autreten.
Gruss Peter
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

@peterpy: tkinter-Programme darf man nicht in Idle laufen lassen, da Idle auch in Tkinter geschrieben ist und nicht sauber die Ausführung davon trennt. Der Fehler im try-Block ist ein Syntaxfehler, so dass das Programm erst gar nicht am Compiler vorbeikommt.
makeRestCall ist gar nicht definiert, wie so einiges andere nicht definiert ist.

@fickAdmiral: wenn Du anfängst, etwas umzuschreiben, dann fange gleich auch an, dich an die Konventionen zu halten: benutze keine *-Importe, Konstanten werden komplett gross geschrieben, Variablennamen und Funktionen dagegen komplett klein. Es darf kein ausführbaren Code auf oberster Ebene geben, es darf keine globalen Variablen geben und vor Du mit GUIs anfängst mußt Du Klassen einigermaßen beherrschen, denn ohne Klassendefinitionen kannst Du kein sauberes GUI-Programm schreiben.
fickAdmiral
User
Beiträge: 5
Registriert: Mittwoch 25. November 2020, 21:35

Sirius3 hat geschrieben: Freitag 4. Dezember 2020, 08:28 @peterpy: tkinter-Programme darf man nicht in Idle laufen lassen, da Idle auch in Tkinter geschrieben ist und nicht sauber die Ausführung davon trennt. Der Fehler im try-Block ist ein Syntaxfehler, so dass das Programm erst gar nicht am Compiler vorbeikommt.
makeRestCall ist gar nicht definiert, wie so einiges andere nicht definiert ist.
die funktionen sind schon da :) ich habe sie hier im beispiel weggelassenl, um den code nicht unnötig aufzublähen. eine makeRestCall() macht ja nichts ausser http-request und ergebniss wieder zurückgeben.
Sirius3 hat geschrieben: Freitag 4. Dezember 2020, 08:28 @fickAdmiral: wenn Du anfängst, etwas umzuschreiben, dann fange gleich auch an, dich an die Konventionen zu halten: benutze keine *-Importe, Konstanten werden komplett gross geschrieben, Variablennamen und Funktionen dagegen komplett klein. Es darf kein ausführbaren Code auf oberster Ebene geben, es darf keine globalen Variablen geben und vor Du mit GUIs anfängst mußt Du Klassen einigermaßen beherrschen, denn ohne Klassendefinitionen kannst Du kein sauberes GUI-Programm schreiben.
Ich werde es beherzigen. Aber auch keine camelCase in python?
Nufnus
User
Beiträge: 18
Registriert: Sonntag 29. November 2020, 21:40

fickAdmiral hat geschrieben: Samstag 5. Dezember 2020, 23:24 Aber auch keine camelCase in python?
Ohne Gewähr, ich versuch mir das auch erst alles anzueignen, aber falls mir niemand widerspricht habe ich es vermutlich richtig verstanden ^^
Dein Beispiel ist lower camel case (um genau zu sein). Bei upper camel case wären dann beide Cs groß, also so: CamelCase
lower camel case nennt man in Python mixedCase

Im PEP 8 Styleguide steht dazu:
Function and Variable Names

Function names should be lowercase, with words separated by underscores as necessary to improve readability.

Variable names follow the same convention as function names.

mixedCase is allowed only in contexts where that's already the prevailing style (e.g. threading.py), to retain backwards compatibility.
Ich würde also sagen: Nein. Es sei denn die anderen machen es auch :mrgreen:
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei das Beispiel was da im PEP8 noch erwähnt wird im Grunde keines mehr ist, denn `threading` bietet mittlerweile auch PEP8-konforme Namen. PySerial und BeautifulSoup wären zwei beliebte externe Bibliotheken die auch von dasIstHaesslich auf das_ist_wunderschoen wechseln. Der Trend geht also in Richtung PEP8. 🙂
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten