Hallo! Mein bisheriger Code:
https://github.com/toxinman/zeug/blob/m ... Vignere.py
Diesen will ich jetzt mittels Tkinter eine Gui verleihen, stehe aber ziemlich auf dem Schlauch. Muss ich eine eigene Klasse erstellen? Oder kann ich einfach eine Funktion erstellen?
Ich habe den auf dieser Seite: http://effbot.org/tkinterbook/entry.htm geschriebenen Code versucht zu bearbeiten, leider hat es nicht funktioniert.
Tkinter Eingabe
Hier meine veränderte Main-Funktion:
Wie kann ich jetzt Sachen aus dem Eingabefeld auffangen?
Fehlermeldung:
Code: Alles auswählen
def main():
"""Hauptfunktion"""
root = tk.Tk()
tk.Label(root, text="Vigenere").pack()
eingabe = tk.Entry(root).pack()
neu = eingabe.get()
root.mainloop()
#text = raw_input("Text: ").upper()
#code = (raw_input("Code: ").upper())*50
#tabelle = [
# list(text),
# list(code)[:len(text)],
# ["0"]*len(text)
#]
tabelle_ausgeben(vigenere_anwenden(tabelle))
Fehlermeldung:
Code: Alles auswählen
Traceback (most recent call last):
File "/Users/ich/Desktop/t.py", line 56, in <module>
main()
File "/Users/ich/Desktop/t.py", line 42, in main
neu = eingabe.get()
AttributeError: 'NoneType' object has no attribute 'get'
@asdfgh: die pack-Methode eines Entry-Objekts liefert eben None als Rückgabewert. Es wäre auch sinnvoller, wenn Du das Entry-Objekt direkt an eine Variable binden würdest. Was erwartest Du, wenn Du direkt nach erstellen den Wert Deines Eingabefeldes abfragst? GUIs verarbeiten Ereignisse. mit einem linearen Programmablauf kommst Du da nicht weiter.
@asdfgh: Man kann das auch funktional lösen, aber objektorientiert wäre in Python ”natürlicher”. Der Punkt ist wie von Sirius3 schon geschrieben wurde, dass GUI-Programmierung nicht linear funktioniert, also nicht *Du* die Reihenfolge des Programmablaufs insgesamt bestimmst, sondern nur in kleinen Abschnitten die auf Ereignisse aus der GUI reagieren. Du musst also den Code der das Eingabefeld ausliest, den Text verschlüsselt, und das Ergebnis irgendwie anzeigt an ein Ereignis binden das von der GUI kommt und vom Benutzer ausgelöst wird. Zum Beispiel die Enter-Taste die im Texteingabefeld betätigt wird, eine zusätzliche Schaltfläche, oder zum Beispiel ein `Tkinter.StringVar`-Objekt an das `Entry`-Objekt beim erstellen als `textvariable` übergeben. Bei `StringVar` kann man dann eine Funktion binden die bei jeder Veränderung des Inhalts aufgerufen wird.
Ok, ich habe mal ein paar Versuche gemacht:
Sollte ich das Programm an sich und die GUI in zwei verschiedene Klassen packen?
Code: Alles auswählen
# -*- coding: UTF8
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
ALPHABET = map(chr, [x for x in range(65,91)])
class Vigenere(object):
def __init__(self):
self.root = tk.Tk()
self.ausgabe = tk.Label(self.root)
self.text = tk.Entry(self.root)
self.codewort = tk.Entry(self.root)
self.button = tk.Button(self.root, text="Codieren", command=self.codieren)
self.text.pack()
self.codewort.pack()
self.button.pack()
self.ausgabe.pack()
self.root.mainloop()
def codieren(self):
text = self.text.get()
codewort = self.codewort.get()
tabelle = [
list(text),
list(codewort)[:len(text)],
["0"]*len(text)
]
tabelle_ausgeben(vigenere_anwenden(tabelle))
def verschieben(buchstabe, verschiebezahl):
"""Buchstaben der Ausgangsnachricht im Alphabet
um Verschiebezahl verschieben"""
neu = chr(ord(buchstabe) + verschiebezahl)
if neu not in ALPHABET:
return chr(ord(neu) - 26)
else:
return neu
def verschiebezahl_ermitteln(buchstabe):
"""Verschiebezahl eines Buchstaben aus dem
Code-Wort ermitteln"""
return ord(buchstabe) - 65
def vigenere_anwenden(tabelle):
"""Vignere-Verschluesselung anwenden"""
for idx, buchstabe in enumerate(tabelle[0]):
tabelle[2][idx] = verschieben(
buchstabe, verschiebezahl_ermitteln(tabelle[1][idx])
)
return tabelle
def tabelle_ausgeben(tabelle):
"""Tabelle bestehend aus Ausgangstext, CodeWort
und Verschluesselung formatiert ausgeben"""
for reihe in tabelle:
print "".join(reihe)
@asdfgh: das einzige was Du beachten solltest ist "Separation of Concerns", dass also Deine Berechnungsfunktionen nichts über Deine GUI und umgekehrt, die GUI nichts über den Inneren Aufbau Deiner Berechnung wissen dürfen.
PS: ein __init__-ialisierter sollte nur Initialisieren und nicht auch noch die ganze Arbeit machen (mainloop). Die vigenere_anwenden-Funktion ist seltsam, da sie die Parameter als Tabelle will, und man sogar noch die Ergebnisliste vorinitialisieren muß. Alles Aufgaben, die die eigentliche Funktion vor dem Anwender verstecken sollte. In diesem Zusammenhang, es ist unüblich in Python mit einem Index explizit auf Tabellen zuzugreifen, wenn man auch über die Elemente iterieren kann. Also:
Und tabelle_ausgeben wäre ja eine Funktion, in der die GUI beteiligt ist.
PS: ein __init__-ialisierter sollte nur Initialisieren und nicht auch noch die ganze Arbeit machen (mainloop). Die vigenere_anwenden-Funktion ist seltsam, da sie die Parameter als Tabelle will, und man sogar noch die Ergebnisliste vorinitialisieren muß. Alles Aufgaben, die die eigentliche Funktion vor dem Anwender verstecken sollte. In diesem Zusammenhang, es ist unüblich in Python mit einem Index explizit auf Tabellen zuzugreifen, wenn man auch über die Elemente iterieren kann. Also:
Code: Alles auswählen
def vigenere_anwenden(text, code):
"""Vignere-Verschluesselung anwenden"""
return [ verschieben(char_text, verschiebezahl_ermitteln(char_code))
for char_text, char_code in zip(text, code)]
Habe das ganze jetzt so gemacht:
Leider stürzt das Programm ab. Außerdem weiß ich nicht, wie ich sowas
ändern soll, weil hier ja die GUI in den Berechnungen auftritt. Leider wird das in meinen Büchern auch so gemacht, deshalb kenne ich keine andere Möglichkeit.
Code: Alles auswählen
# -*- coding: UTF8
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
ALPHABET = map(chr, [x for x in range(65, 91)])
class Vigenere(object):
def __init__(self):
self.root = tk.Tk()
self.text = tk.Entry(self.root)
self.code = tk.Entry(self.root)
self.button = tk.Button(
self.root, text="Codieren",
command=self.vigenere_anwenden
)
self.ausgabe = tk.Label(self.root)
self.text.pack()
self.code.pack()
self.button.pack()
self.ausgabe.pack()
def vigenere_anwenden(self):
text = self.text.get()
code = self.code.get()
self.ausgabe.config(text="".join([
self.verschieben(char_text, self.verschiebezahl_ermitteln(char_code))
for char_text, char_code in zip(text, code)
]))
def verschieben(self, buchstabe, verschiebezahl):
neu = chr(ord(buchstabe) + verschiebezahl)
if neu not in ALPHABET:
return chr(ord(neu) - 26)
else:
return neu
def verschiebezahl_ermitteln(self, buchstabe):
return ord(buchstabe) - 65
def run(self):
self.root.mainloop()
if __name__ == '__main__':
vigenere = Vigenere()
vigenere.run()
Code: Alles auswählen
def vigenere_anwenden(self):
text = self.text.get()
code = self.code.get()
self.ausgabe.config...
Du schreibst einfach zwei Funktionen dafür. Die erste wird beim Klick auf den Button aufgerufen, liest die Werte der Widgets aus und wandelt ggf. noch die Eingaben in Integer, Floats oder welcher Datentyp auch immer gebraucht wird. Dann ruft die Funktion die reine Berechnungsfunktion auf, nimmt dessen Ergebnis entgegen und zeigt das dann ggf. an.asdfgh hat geschrieben:ändern soll, weil hier ja die GUI in den Berechnungen auftritt. Leider wird das in meinen Büchern auch so gemacht, deshalb kenne ich keine andere Möglichkeit.Code: Alles auswählen
def vigenere_anwenden(self): text = self.text.get() code = self.code.get() self.ausgabe.config...
Das Leben ist wie ein Tennisball.
Danke für den Tipp . Jetzt sieht das ganze so aus:
Leider hängt es sich immer noch bei Betätigen des Buttons auf. Wie finde ich die Ursache davon?
Code: Alles auswählen
def __init__(self):
self.root = tk.Tk()
self.text = tk.Entry(self.root)
self.code = tk.Entry(self.root)
self.button = tk.Button(
self.root, text="Codieren",
command=self.button_clicked
)
self.ausgabe = tk.Label(self.root, text="Text und Codewort eingeben")
self.text.pack()
self.code.pack()
self.button.pack()
self.ausgabe.pack()
def button_clicked(self):
text = self.text.get()
code = self.code.get()
ergebnis = "".join(self.vigenere_anwenden(text, code))
self.ausgabe.config(text=ergebnis)
def vigenere_anwenden(self, text, code):
return [
self.verschieben(
char_text, self.verschiebezahl_ermitteln(char_code))
for char_text, char_code in zip(text, code)
]
...
def run(self):
self.root.mainloop()
In dem Fall fehlt allerdings der Quelltext in dem das Problem ist, denn im bisher gezeigten sehe ich keine solche Schleife.
Hier der aktuelle Quelltext:
Zum Trennen von GUI und Logik muss ich die Logik-Funktionen außerhalb der Klasse schreiben und in der Klasse aufrufen?
Code: Alles auswählen
# -*- coding: UTF8 -*-
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
ALPHABET = map(chr, [x for x in range(65, 91)])
class Vigenere(object):
def __init__(self):
self.root = tk.Tk()
self.text = tk.Entry(self.root)
self.code = tk.Entry(self.root)
self.button = tk.Button(
self.root, text="Codieren", command=self.button_clicked)
self.ausgabe = tk.Label(self.root, text="Text und Codewort eingeben")
self.text.pack()
self.code.pack()
self.button.pack()
self.ausgabe.pack()
def button_clicked(self):
text = self.text.get()
code = self.code.get()
ergebnis = "".join(self.vigenere_anwenden(text, code))
self.ausgabe.config(text=ergebnis)
def vigenere_anwenden(self, text, code):
return [
self.verschieben(
char_text, self.verschiebezahl_ermitteln(char_code))
for char_text, char_code in zip(text, code)
]
def verschieben(self, buchstabe, verschiebezahl):
neu = chr(ord(buchstabe) + verschiebezahl)
if neu not in ALPHABET:
return chr(ord(neu) - 26)
else:
return neu
def verschiebezahl_ermitteln(self, buchstabe):
return ord(buchstabe) - 65
def run(self):
self.root.mainloop()
if __name__ == '__main__':
vigenere = Vigenere()
vigenere.run()
@asdfgh: Ich sehe da keine Endlosschleife. Also weder im Code, noch hängt da irgendwas wenn ich das Programm ausführe.
Die Verschlüsselung ist allerdings fehlerhaft, da verschwindet Text wenn man Text/Code eingibt der nicht irgendwelchen Bedingungen entspricht.
Die Verschlüsselung ist allerdings fehlerhaft, da verschwindet Text wenn man Text/Code eingibt der nicht irgendwelchen Bedingungen entspricht.