Отделение проблем пользовательского интерфейса 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()

Надеюсь, это будет полезно. Я знаю, что здесь не так много объяснений, но у меня не так много времени, чтобы написать это. Ваша проблема очень общая.

Другие вопросы по тегам