Отделение проблем пользовательского интерфейса Tkinter от приложения Logic in Python
Это мое первое приложение в мире. Это работает хорошо, но я хотел бы отделить проблемы пользовательского интерфейса, такие как получение ввода и создание меток, от логики перевода. Затем я хотел бы удалить выходные данные из предыдущего перевода, т. Е. Отображать только один перевод на экране за раз.
Как я могу отделить логику перевода от моего графического интерфейса Tkinter?
from Tkinter import *
import tkMessageBox
def start():
inputg = input.get()
if len(inputg) >= 2 and inputg.isalpha():
new_word_out = Label(text=(inputg[1:] + (inputg[0] + "ay")).lower().title()).pack()
out_message = Label(text="Cool! Try another!").pack()
# restart()
elif len(inputg) <= 1 and inputg.isalpha():
show_error(message="Whoops! I need 2 or more characters to translate! Try again!")
return
elif len(inputg) >= 1 and not inputg.isalpha():
show_error(message="Whoops! No numbers or symbols please! Try again!")
return
elif len(inputg) == 0:
show_error(message="It seems you haven't given me anything to translate!")
return
def show_error(message):
tkMessageBox.showerror(title="Error", message=message)
return
def quit():
ask_exit = tkMessageBox.askyesno(title="Quit", message="Are you sure you want to quit?")
if ask_exit > 0:
root.destroy()
return
root = Tk()
input = StringVar() # stores user input into this variable as a string.
root.title("The Pig Translator")
root.protocol("WM_DELETE_WINDOW", quit)
labeltitle1 = Label(text="Hello there! This is my Pig Latin Translator!").pack()
labeltitle2 = Label(text="Please enter a word to continue!", fg='darkgreen', bg='grey').pack()
original_entry = Entry(textvariable=input, bd=5, fg='darkgreen').pack()
translate_button = Button(text="Translate", command=start).pack()
root.bind('<Return>', lambda event: start()) # essentially binds 'Return' keyboard event to translate_button
root.mainloop()
1 ответ
Есть много способов отделить логику от GUI. как правило, я бы рекомендовал использовать классы и функции обратного вызова. Таким образом, я сделал класс, который генерирует графический интерфейс. Однако перевод выполняется внешней функцией, которая называется do_translation
,
MyFrame не знает много о том, как do_translation
, Он только знает, что возвращает translated_str, message
и принимает строку в качестве аргумента. do_translation
также не транслируется ни на один графический интерфейс. do_translation
принимает только входную строку, делает то, что хочет, и возвращает переведенную строку и сообщение. MyFrame принимает эту функцию в качестве обратного вызова. Вы можете сделать любую другую функцию перевода, и пока ввод и вывод одинаковы, она будет работать.
Я полагаюсь здесь на "Крутой" массаж, который показывает, что перевод был в порядке. Его плохая идея сделать так, чтобы он передавал слово "Круто", но не хотел слишком сильно менять свой код. Вероятно, лучше поднять ошибку или использовать коды сообщений и т. Д.
from Tkinter import *
import tkMessageBox
class MyFrame(Frame):
def __init__(self, master, input_callback=None, **kwargs):
Frame.__init__(self, master)
self.set_input_callback(input_callback)
self.create_widgets()
self.pack()
def create_widgets(self):
self.input = StringVar() # stores user input into this variable as a string.
self.labeltitle1 = Label(text="Hello there! This is my Pig Latin Translator!")
self.labeltitle1.pack()
self.labeltitle2 = Label(text="Please enter a word to continue!", fg='darkgreen', bg='grey')
self.labeltitle2.pack()
self.original_entry = Entry(textvariable=self.input, bd=5, fg='darkgreen')
self.original_entry.pack()
self.translate_button = Button(text="Translate", command=self.start)
self.translate_button.pack()
self.new_word_out = Label(text='')
self.out_message = Label(text='')
def set_input_callback(self, some_fun):
self.input_callback = some_fun
def show_error(self, message):
tkMessageBox.showerror(title="Error", message=message)
return
def start(self):
inputg = self.input.get()
if self.input_callback:
translated_str, message = self.input_callback(inputg)
if 'Cool' in message:
self.new_word_out['text'] = translated_str
self.new_word_out.pack()
self.out_message['text'] = message
self.out_message.pack()
else:
self.show_error(message)
def do_translation(inputg):
translated_str = message = ''
if len(inputg) >= 2 and inputg.isalpha():
translated_str = (inputg[1:] + (inputg[0] + "ay")).lower()
message = "Cool! Try another!"
elif len(inputg) <= 1 and inputg.isalpha():
message = "Whoops! I need 2 or more characters to translate! Try again!"
elif len(inputg) >= 1 and not inputg.isalpha():
message = "Whoops! No numbers or symbols please! Try again!"
elif len(inputg) == 0:
message = "It seems you haven't given me anything to translate!"
return translated_str, message
def quit():
ask_exit = tkMessageBox.askyesno(title="Quit", message="Are you sure you want to quit?")
if ask_exit > 0:
root.destroy()
return
root = Tk()
root.title("The Pig Translator")
root.protocol("WM_DELETE_WINDOW", quit)
mf = MyFrame(root)
mf.set_input_callback(do_translation)
root.bind('<Return>', lambda event: start()) # essentially binds 'Return' keyboard event to translate_button
root.mainloop()
Надеюсь, это будет полезно. Я знаю, что здесь не так много объяснений, но у меня не так много времени, чтобы написать это. Ваша проблема очень общая.