将 Tkinter UI 关注点与 Python 应用程序中的逻辑分离

2024-04-06

这是我的第一个应用程序。它运行良好,但我想将 UI 问题(例如获取输入和创建标签)与翻译逻辑分开。然后,我想删除先前翻译的输出,即一次仅在屏幕上显示一个翻译。

如何将翻译逻辑与 Tkinter GUI 分开?

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()

有很多方法可以将逻辑与 GUI 分开。一般来说,我建议使用类和回调函数。因此,我创建了一个生成 gui 的类。然而,翻译是由称为的外部函数执行的do_translation.

MyFrame不太了解如何do_translation。它只知道它返回translated_str, message并以字符串作为参数。do_translation也不依赖任何 GUI。这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()

希望这会有用。我知道,没有太多解释这里发生的事情,但是,没有太多时间来写它。你的问题很普遍。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 Tkinter UI 关注点与 Python 应用程序中的逻辑分离 的相关文章

随机推荐

  • 托管配置文件中的 Android 请勿打扰 (DnD) 权限

    我有以下问题 我的应用程序分布在 MDM 系统上 并在 Android for Work 中运行 在某些情况下 应用程序必须暂时终止 DnD 模式 为此 用户必须在应用程序启动时授予 DnD 权限 到目前为止 一切都很好 如果我将应用程序安
  • 我正在寻找一个简单但实​​用且强大的 .net IOC/DI 框架

    我将在一个由经验较少的开发人员组成的项目中使用它 因此像 Spring NET 这样的复杂框架不是一个选择 我在想 Ninject 温莎城堡 结构图 哪个会提供适度的学习曲线而不失去灵活性 另一个问题 放置配置的正确位置在哪里 由于 3 层
  • 错误:index_not_found_Exception

    我使用 ELK 堆栈来分析我的日志文件 我上周测试过 一切正常 今天 我进行了测试 但当我输入 http localhost 9200 iot log count http localhost 9200 iot log count iot
  • 使用持续时间匹配组合三个不同的时间戳数据帧

    我有三个具有不同数据帧和频率的数据帧 我想将它们组合成一个数据框 第一个数据框收集来自太阳的阳光 如下所示 df1 index light data 05 01 2019 06 54 00 000 10 05 01 2019 06 55 0
  • javascript:长按书签

    我需要识别 JavaScript 书签中的长按 所以 我不能使用 jQuery 也不能使用 onclick 事件和类似事件 这可能吗 如何实现 onmousedown call setTimeout 在长按期间 如果允许超时 它将调用其函数
  • 如何并排放置两个 iframe

    我尝试了几种代码 例如下面的代码 div class box div div div
  • 我们可以在数据绑定中连接两个属性吗?

    我们可以在绑定表达式中将两个属性连接在一起吗 如果可能的话 无需转换器或无需编写两个文本块并单独设置它们 如果你想展示 请说FirstName and LastName 在一个单一的TextBlock 那么你可以这样做
  • 在 Internet Explorer 中使表单元素 onchange 冒泡

    如何使各种表单元素的 onChange 事件向上冒泡到 Internet Explorer 中的父表单对象 当选择框 单选按钮 几乎任何内容 在 IE 中发生更改时 不会触发父窗体的 onChange 我的表单是动态变化的 因此很难通过监听
  • 如何在rails中设置postgresql命令超时

    我正在使用heroku 和heroku postgresql 如何设置 db 命令超时 以便在 sql 命令花费时间超过 10 秒时出现异常 像这样配置你的database yml 关键是变量哈希 defaults default adap
  • 意外提交敏感信息 - GitLab

    我不小心提交了包含敏感数据的文件 我需要通过删除敏感数据来更新该文件 并确保旧版本不会出现在历史记录中 据我所知 那些在本地克隆了存储库的人仍然可以访问它 但是 一旦他们提取最新的数据 是否可以通过设置方式让他们看不到敏感数据继续前进或无法
  • 从矩阵中提取行并在 MATLAB 中创建一个新矩阵

    我有一个矩阵 X 1 1 2 2 3 3 4 4 Y 2 4 我想要一个结果矩阵z只有第 2 行和第 4 行 中的值Y of X 那是 Z 2 2 4 4 有什么解决办法吗 Z X Y 在我看来 这是一个很容易研究的问题 第一个结果 htt
  • 使用 ViewModel 中的多态性绑定到 XAML 中带有参数的方法

    我的 ResultView 中有一个带有六个选项卡的 TabControl 位于此视图后面的 ViewModel 可以是 ResultTypeOneViewModel 或 ResultTypeTwoViewModel 它们均派生自 Resu
  • Puppeteer 中的多浏览器与多选项卡

    我有 100 个网页 必须测试运行时错误 我发现 Puppeteer 插件可以 毫不费力 地做到这一点 但我遇到了一个困境 启动一个带有多个选项卡的浏览器 或者为每个链接创建一个新的浏览器 在这种情况下最好的方法是什么 我听说 在有多个选项
  • 为什么我的 Google 地图 API 密钥无效?

    这是我的第一个问题 我在研究中没有找到答案 我在旧网站 不是我的网站 上的 google 地图 API 密钥出现问题 tao yin com 法国气功协会 有两个月的时间 我为这个网站做了一张地图 在两个地方 Here http www t
  • 如何在 ncurses 中获得亮白色?

    如何初始化浅灰色背景和亮白色前景的颜色对 init pair number COLOR WHITE COLOR WHITE 创建一个具有浅灰色前景和背景的颜色对 但我需要前景是真正的白色 我尝试将 COLOR WHITE 与 A BLINK
  • 如何在 Rails webpacker 3 中使用 jQuery

    我生成一个新的 Rails 应用程序 rails new titi webpack vue 并想使用 jQuery 或其他库 如 popper vue resource 我尝试过了yarn add jquery这很好 但我无法在 JavaS
  • Gitlab6.0和Apache2

    请问如何使用Apache2设置Github 6 0 按照原来的说明安装Gitlab Unicorn rb 中的调整 listen home git gitlab tmp sockets gitlab socket backlog gt 64
  • python 使用图像谷歌图像进行搜索

    我在用 python 搜索谷歌图像搜索时遇到了非常困难的情况 我需要只使用标准 python 库 所以 urllib urllib2 json 有人可以帮忙吗 假设图像是 jpeg jpg 并且位于我运行 python 的同一文件夹中 我尝
  • Angular + ui-router:$stateChangeSuccess 在状态 b 上触发,但不在 a.b 上触发

    用户界面路由器 0 2 11 AngularJS 1 3 0 我很难理解为什么 BarCtrl 中的 stateChangeSuccess 事件处理程序没有在 foo bar 上触发 它在 bar 上触发 foo bar gt Consol
  • 将 Tkinter UI 关注点与 Python 应用程序中的逻辑分离

    这是我的第一个应用程序 它运行良好 但我想将 UI 问题 例如获取输入和创建标签 与翻译逻辑分开 然后 我想删除先前翻译的输出 即一次仅在屏幕上显示一个翻译 如何将翻译逻辑与 Tkinter GUI 分开 from Tkinter impo