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

person Brandon Force    schedule 15.01.2015    source источник
comment
Не ответ на ваш вопрос. В вашем коде labeltitle1 будет иметь значение None, поскольку Widget.pack возвращает None. Я видел, как этот укус слишком много людей, чтобы не комментировать это ... :-)   -  person mgilson    schedule 15.01.2015
comment
Связано: зависание программы во время выполнения функции в Tkinter   -  person Stevoisiak    schedule 14.03.2018


Ответы (1)


Есть много способов отделить логику от графического интерфейса. обычно я бы рекомендовал использовать классы и функции обратного вызова. Таким образом, я сделал класс, который генерирует графический интерфейс. Однако перевод выполняется внешней функцией с именем 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()

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

person Marcin    schedule 15.01.2015