Mein Programm hängt sich immer auf... (Tkinter)

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
Adri
User
Beiträge: 6
Registriert: Sonntag 31. Oktober 2021, 19:21

Hi, Ich soll für die Schule ein Verschlüsselungsprogramm schreiben. Ich habe mich für die Caeser Verschüsselung entschieden. An für sich funktioniert das Programm. Doch nun habe ich es in Tkinter implementiert und immer wenn ich auf einen er Beiden Buttons drücke hängt sich das Programm auf und es stürtzt ab. Zudem wird die eingabe aus dem ersten Entryfeld in der Shell ausgegeben.

Code: Alles auswählen

from tkinter import *
def Code():
    code = input(b.get())
    Verschiebung = int(input(d.get()))
    coded = "".join(chr((ord(char) + Verschiebung) % 256) for char in code)
    h.config(text=coded)
def Encode():
    code = input(b.get())
    x = int(input(d.get()))
    Verschiebung = -x
    encoded = "".join(chr((ord(char) + Verschiebung) % 256) for char in code)
    h.config(text=encoded)

F = Tk()
F.title('Coding')
F.geometry('500x500')
F.config(bg='gray')

a = Label(master=F, text='Eingabe:', fg='white', bg='black', font=('Arial',16))
a.place(x=50, y=50, width=200, height=50)
b = Entry(master=F, text='', font=('Arial',16))
b.place(x=275, y=50, width=200, height=50)
c = Label(master=F, text='Schlüssel:', fg='white', bg='black', font=('Arial',16))
c.place(x=50, y=125, width=200, height=50)
d = Entry(master=F, text='', font=('Arial',16))
d.place(x=275, y=125, width=200, height=50)
e = Button(master=F, text='Verschlüsseln', fg='white', bg='black', font=('Arial',16), command=Code)
e.place(x=50, y=200, width=200, height=50)
g = Button(master=F, text='Entschlüsseln', fg='white', bg='black', font=('Arial',16), command=Encode)
g.place(x=275, y=200, width=200, height=50)
h = Label(master=F, text='', font=('Arial',16))
h.place(x=50, y=275, width=425, height=50)

F.mainloop()
Hier zur Überprüfung nochmal das Programm ohne Tkinter:

Code: Alles auswählen

def Code():
    code = input("Code: ")
    Verschiebung = int(input("Verschiebungsfaktor: "))
    coded = "".join(chr((ord(char) + Verschiebung) % 256) for char in code)
    print("Verschlüsselter Code:", coded)
def Encode():
    code = input("Verschlüsselung: ")
    x = int(input("Verschiebungsfaktor: "))
    Verschiebung = -x
    encoded = "".join(chr((ord(char) + Verschiebung) % 256) for char in code)
    print("Entschlüsselter Code:", encoded)
Ich würde mich wirklich freuen, wenn mir jemand sagen könnte wo das Problem liegt.

Danke
narpfel
User
Beiträge: 691
Registriert: Freitag 20. Oktober 2017, 16:10

@Adri: Was macht die `input`-Funktion? Und wie spielt das mit einer GUI zusammen?

Abgesehen von dem Problem solltest du dringend besser verständliche Variablennamen benutzen. In zwei Tagen hast du keine Ahnung mehr, was der Unterschied zwischen `b`, `d` und `g` ist.
Benutzeravatar
__blackjack__
User
Beiträge: 14077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Adri: Die Ver- und Entschlüsselung ist IMHO ein bisschen problematisch, weil man nicht jeden verschlüsselten Text…

a) …für das entschlüsseln wieder eingeben kann, denn im Bereich 0 bis 255 gibt es auch nicht darstellbare/druckbare Steuerzeichen.
b) …auch wieder ins Original zurückverwandeln kann, denn es werden alle Zeichen mit einem Code-Point >255 auf den Bereich 0 bis 255 abgebildet.

Ansonsten haben `Code()` und `Encode()` falsche Namen. `Encode` heisst auf Deutsch *ver*schlüsseln, das ist bei Dir aber die Funktion die *ent*schlüsselt, also genau das Gegenteil macht. Wenn man dann noch berücksichtigt, dass alles ausser Konstanten und Klassen in Python klein_mit_unterstrichen benannt wird, müsste `Code` eigentlich `encode()` und und `Encode()` eigentlich `decode()` heissen.

Man sollte Programmlogik und Benutzerinteraktion nicht vermischen. Das heisst diese beiden Funktionen sollten nur genau das tun: ver- und entschlüsseln. Weder den Benutzer etwas fragen, noch etwas ausgeben. Dann sind die einfach isoliert testbar, was zur Fehlersuche praktisch ist, und auch universeller verwendbar. Zum Beispiel kann man dann mit den gleichen beiden Funktionen sowohl ein Konsolenprogramm als auch ein GUI-Programm schreiben, ohne das man in beiden Fällen die Ver- und Entschlüsselung jeweils noch mal programmieren muss.

Bei so einer Verschiebe-Chiffre fällt dann auch auf, dass man eigentlich nur eine Funktion braucht für die Arbeit, denn die beiden Funktionen gleichen sich bis auf ein winziges Detail, das man dann als Argument übergeben kann.

Von einer GUI würde ich an Deiner Stelle noch die Finger lassen und erst objektorientierte Programmierung lernen, denn die braucht man für jede nicht-triviale GUI. Oder zumindest gutes Verständnis von Funktionen inklusive Closures/`functools.partial()`.

Fenstergrösse, Schriftgrössen, und Ort und Grösse von Anzeigeelementen gibt man nicht absolut an. Das mag bei Dir funktionieren/passend aussehen, aber das kann auf anderen Rechnern mit anderen Einstellungen komplett komisch aussehn, bis hin zu unbenutzbar sein, weil Elemente nicht mehr in den absoluten Fensterplatz passen und nicht angezeigt werden, oder Elemente von anderen teilweise oder ganz verdeckt werden. Wenn man `grid()` oder `pack()` verwendet, hat man das Problem nicht, und man muss auch die Fenstergrösse nicht vorgeben, weil es automatisch genau so gross wird, das alles rein passt und sich nichts überlappt oder grössere Lücken entstehen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Adri
User
Beiträge: 6
Registriert: Sonntag 31. Oktober 2021, 19:21

Hi, danke für die schnellen Antworten.
@narpfel: Die Input funktion speichert den Text der mit .get() genommen wird als String. Dieser soll dann via char Verschlüsselt werden und dann in dem letzten label dann wieder ausgegeben werden.

@blackjack, danke für die hinweise, ich werde mir das nochmal gründlich ansehen. Ja, das mit der GUI könnte ich besser machen. Sieht das Programm bei dir Funktionsfähig aus?? Ich bin dir dankbar für deine Hinweise, aber mein Problem löst das jetzt noch nicht so wirklich. Falls das Programm bei dir Funktionsfähig aussieht wenn du es ausführst, würde ich dich Bitten einen random Text in das erste Entryfeld zu schreiben und irgendeine Zahl in das zweite Entryfeld, und dann auf Verschlüsseln oder auf Entschlüsseln zu drücken. Das Problem ist, dass das Programm dabei immer abstürtzt.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

input ist eine blockierende Eingabefunktion, die versucht, von der Standardeingabe zu lesen. Das hat in einer GUI-Anwendung nichts zu suchen. Darauf wollte narpfel dich stossen.
Adri
User
Beiträge: 6
Registriert: Sonntag 31. Oktober 2021, 19:21

Hi deets,
was kann ich denn Anstelle der Inputfunktion verwenden?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na du definierst doch Entry-Objekte. Die beinhalten doch deine Eingabe. Warum denkst du, da muss ueberhaupt noch etwas um das .get() herum?
Adri
User
Beiträge: 6
Registriert: Sonntag 31. Oktober 2021, 19:21

Weil die def-Funktion ja wissen muss mit welchem Entryfeld diese welche Variable definieren muss.
Adri
User
Beiträge: 6
Registriert: Sonntag 31. Oktober 2021, 19:21

@deets, Danke, dass war tatsächlich die Lösung des Problems. Ich muss mich wohl nochmal etwas genauer mit den Grundlagen beschäftigen.
Antworten