【问题标题】:tk: how to invoke it just to display something, and return to the main program?tk:如何调用它只是为了显示一些东西,然后返回主程序?
【发布时间】:2011-06-16 09:12:43
【问题描述】:

抱歉这个菜鸟问题,但我真的不明白。

我正在使用 python / tkinter,我想显示一些东西(比如,上面有一些形状的画布),并保持显示直到程序退出。我知道在我致电tkinter.tk.mainloop() 之前不会显示任何小部件。但是,如果我调用tkinter.tk.mainloop(),在用户关闭主窗口之前我将无法执行任何其他操作。

我不需要监控任何用户输入事件,只是显示一些东西。在不放弃对mainloop 的控制权的情况下,有什么好的方法可以做到这一点?

编辑:

这个示例代码合理吗:

class App(tk.Tk):
  def __init__(self, sim):
    self.sim = sim # link to the simulation instance
    self.loop()

  def loop():
    self.redraw() # update all the GUI to reflect new simulation state
    sim.next_step() # advance simulation another step
    self.after(0, self.loop)

  def redraw():
    # get whatever we need from self.sim, and put it on the screen

EDIT2(添加 after_idle):

class App(tk.Tk):
  def __init__(self, sim):
    self.sim = sim # link to the simulation instance
    self.after_idle(self.preloop)

  def preloop():
    self.after(0, self.loop)

  def loop():
    self.redraw() # update all the GUI to reflect new simulation state
    sim.next_step() # advance simulation another step
    self.after_idle(self.preloop)

  def redraw():
    # get whatever we need from self.sim, and put it on the screen

【问题讨论】:

  • 这是多线程的用武之地吗?
  • @max:非常接近。这是正确的概念,尽管我建议不要在值为零之后给予。 GUI 事件不应该花费很长时间,但它们花费的时间超过零毫秒。您必须使用该值来感受是什么提供了良好的 GUI 性能,同时仍然让您的主要逻辑以最快的速度运行。
  • @Bryan:我不敢测试延迟值;如果程序稍后在另一个环境中运行(例如,使用不同的分辨率等)怎么办?也许我应该改用after_idle - 这会解决问题还是有其他问题?
  • @max: 使用after_idle 可能会锁定您的GUI。空闲任务一直运行,直到空闲队列上没有任何内容,因此如果您在空闲期间执行某些操作,将某些内容放入队列,则队列永远不会为空。普遍接受的解决方案是after_idle 调用具有零值的after 来安排您的工作。这使 tk 有机会处理所有空闲事件(例如屏幕重绘),然后在运行回调之前处理任何其他事件(例如鼠标移动)。
  • 谢谢 - 你指的是我编辑的代码吗?

标签: python user-interface tkinter


【解决方案1】:

Tk 需要一个事件循环,这是无法避免的。例如,这就是小部件知道在被遮挡时重绘自己的方式。所以,你必须让事件循环运行。

您至少有三个选择。首先,将主线程用于 GUI,并将其他逻辑放在单独的线程中。第二种选择是使用两个单独的进程 - 一个用于 GUI,一个用于您的程序。您的程序可以通过套接字与 GUI 通信,以向其发送数据以进行显示。

您的第三个选择是学习在事件循环中生活。毕竟,它实际上只不过是包装了整个程序的while True。如果您的主逻辑在循环中运行,只需取出循环并将其替换为事件循环。例如,您可以运行代码的一次迭代,然后让它调用after 来安排自己在几毫秒内再次运行。对after 的调用添加了一个事件,该事件将在GUI 完成任何必要的维护时调用您的代码。

【讨论】:

  • 谢谢。我害怕 Python 中的线程,特别是因为即使是 GUI 主循环也可能最终会执行一些 CPU 密集型任务,而不仅仅是 I/O 等待。流程听起来很棒 - 但是否有很多开销?
  • 我用第三个解决方案的代码示例更新了我的问题。你是这个意思吗?
  • 害怕线程是一种很好的本能。尽管 python 使它们相当简单,但总的来说,线程是困难的并且增加了复杂性。如果可以避免,IMO,请避免。
猜你喜欢
  • 2021-04-22
  • 1970-01-01
  • 2018-08-09
  • 2010-10-01
  • 2011-09-28
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多