【问题标题】:How to create a light GUI with TkInter如何使用 TkInter 创建轻量级 GUI
【发布时间】:2015-09-27 17:29:43
【问题描述】:

我正在编写一个程序来读取和修改包含有关某些图像的信息的二进制文件:但是为了能够做到这一点,它还需要用户提供一些信息,假设这些图像所在的文件夹很少选择。

通过对网络的快速研究,我发现创建 GUI 的一种简单方法是 Tkinter,事实上我很快就达到了我的目标。 特别是我使用了tkFileDialogtkMessageBox 模块,而无需调用mainloop 函数,只要我想在屏幕上显示一些东西就创建和销毁一个窗口:我认为这不是正确的方法,但它非常适合我的应用程序,因为通过这种方式,我能够在需要与用户“交谈”之前让程序保持原样,而无需使用纯面向对象的结构来重构它,例如“真正的”GUI。

当我想改进此界面并使用 按钮 小部件以提供在三个选项中进行选择的可能性时出现了问题:在这种情况下,mainloop 似乎是强制性的..

所以问题来了:是否存在一种无需将所有函数都放入 GUI 类且不使用无限循环即可与用户交流的策略? (我认为使用 Tkinter 的答案是否定的) 在这种混合情况下,最好的方法是什么?

【问题讨论】:

  • 运行一个无限的“事件循环”基本上是 GUI 应用程序的运行方式,一旦它退出应用程序就会关闭。所以不,你不能避免主循环,尝试没有意义。
  • @AcidReign:不一定。例如,在 Windows 上,你当然可以做一些非 UI 工作,呈现一个窗口并运行一个消息循环,让消息循环终止并做更多非 UI 工作,然后呈现另一个窗口并运行另一个消息循环……在 Windows 上,通常模式对话框也是通过嵌套的消息循环实现的,所以它真的不像你建议的那么简单。
  • 好吧,如果你想学究气(j/k),我承认你当然可以运行一个有限/显式的阻塞调用序列,显示对话框并等待响应,因为你建议。但这将是一个相当基本/无趣的 GUI
  • @ReblochonMasque:谢谢你的建议,我几乎阅读了所有关于如何构建 Tkinter 项目的 stackoverflow 问题,但不是那个。无论如何,我认为在我的情况下,GUI 不那么重要,而不是该示例中的核心。对我来说奇怪的是(并且 AcidReign 证实了这一点)是没有讨论过有一个应用程序的生命与他的 GUI 部分没有严格相关的应用程序,而以我为例,GUI 部分只是其中的一小部分总任务..

标签: python user-interface tkinter


【解决方案1】:

我已经拼好了一个骨架。几点说明:

  1. 这是一个简单的例子,只有三个函数接受 1 个或 2 个参数。然而,让它适应更多的函数和参数应该是直截了当的。
  2. 我绝对不提倡在实际程序中使用短变量名。
  3. 考虑在 base.py 中使用 a) 类,如果它适合您的逻辑 b) 在 GUI.py 中稍长一些时使用
  4. 使用grid 可选参数来获得漂亮的GUI。

总结上面的 cmets,目标是分离不同的部分:第一个模块将包含所有计算,但不会处理用户输入,第二个模块将处理命令行用户输入并依赖于第一个一个用于计算,第三个将使用图形界面,并且还依赖第一个进行计算。您还可以添加第四个进行测试。 当然,只要您知道原因,就可以随意修改此模式。

欢迎评论。

第一个模块:

#file base.py
def f1(input1):
    ...
    return res1

def f2(res1, input2):
    ...
    return res2

def f3(res2):
    ...
    return res3

if __name__ == '__main__':
    r1 = f1('directoryPath')
    r2 = f2(r1, 'fileName')
    r3 = f3(r2)

第二个模块:

#file commandline.py
from base import *

i1 = input() # in 3.X, raw_input in 2.X
r1 = f1(i1)

i2 = input() # in 3.X, raw_input in 2.X
r2 = f2(r1, i2)
r3 = f3(r2)

第三个模块:

#file GUI.py
from base import *
import tkinter as tk # in 3.X, Tkinter in 2.X

def compute():
    i1 = e1.get()
    r1 = f1(i1)

    i2 = e2.get()
    r2 = f2(r1, i2)
    r3 = f3(r2)

    l1.configure(text = r3) #if r3 is a string else str(r3) 

app = tk.Tk()
e1 = tk.Entry(app)
e1.grid()

e2 = tk.Entry(app) 
e2.grid()

b1 = tk.Button(app, text = "Compute", command = compute)
b1.grid()

l1 = tk.Label(app)
l1.grid()

app.mainloop()

【讨论】:

  • 感谢 Eric 的回答!我想我错过了一个关键点:第一个模块如何启动 GUI(或命令行部分)?似乎第一个是“主要”的,但我不明白哪个是其他的逻辑,因为它们不仅包含类或函数,还包含一些单一的指令。无论如何,感谢您的时间和解释!
  • @giubacchio:第一个模块无法启动其他模块。它可能包含几乎所有代码,但您使用其他代码之一来启动命令行版本或 GUI 版本。您也可以将所有代码放在一个模块中,特别是如果您总是想启动 GUI 版本。
  • 我一直在寻找的可能是将主要结构作为您的第一个模块之一,并且能够调用像 GUI.py 这样的模块,可能不止一次,以便向用户询问一些信息。我不知道这是否可能,因为这样会发生多个主循环(但不是同时发生),这通常是不允许的。实现我的目标的一种方法是将所有主要计算放在 GUI 中调用的函数中(假设使用开始按钮),并在我需要一些信息时询问用户。但我不太喜欢这个解决方案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-11
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
  • 2011-11-11
相关资源
最近更新 更多