为什么gtk.main_quit()不起作用?

时间:2014-03-18 15:53:23

标签: python-2.7 gtk pygtk

我是新来的。 :)

我无法从C中的GTK +移植到PyGTK,特别是我不明白为什么(在暂停/播放按钮的特定上下文中)gtk.main_quit()即使被调用也什么都不做。

在我的工作示例中,按“播放”后,按“暂停”,然后尝试使用“退出”按钮。在我的结尾“退出”按钮,即使它调用gtk.main_quit()(并在它之后打印东西来证明它确实),也不会对程序产生任何影响。关于我做错了什么想法?

这是:

import pygtk
pygtk.require('2.0')
import gtk, gobject, cairo
import time

global paused
paused = False
running = False

def some_stuff(widget, data=None):
  global paused
  global running
  x = 0
  if running:
    return
  running = True
  paused = False
  while True:
    x += 1
    print x
    while gtk.events_pending():
      gtk.main_iteration(False)
    while paused:
      while gtk.events_pending():
    gtk.main_iteration(False)
  running = False
  paused = False

def pause_stuff(widget, data=None):
  global paused
  paused = not paused

def force_quit(widget, data=None):
  print 'before'
  gtk.main_quit()   # doesn't work, gtk main loop keeps running
  #exit()            # obviously works to kill everything
  print 'after'


def main():
  window = gtk.Window()
  window.connect("delete-event", force_quit)
  window.show()
  vbox = gtk.VBox(True, 3)
  vbox.show()
  window.add(vbox)

  button = gtk.Button("Play")
  button.connect("clicked", some_stuff, None)
  vbox.add(button)
  button.show()

  button = gtk.Button("Pause")
  button.connect("clicked", pause_stuff, None)
  vbox.add(button)
  button.show()

  button = gtk.Button("Quit")
  button.connect("clicked", force_quit, None)
  vbox.add(button)
  button.show()
  window.present()
  gtk.main()
  return 0

if __name__ =="__main__":
  main()

2 个答案:

答案 0 :(得分:2)

gtk.main_quit()指示GTK主循环终止。它对您的代码没有影响,因为您的some_stuff()函数实现了自己的主循环版本,不受调用gtk.main_quit()的影响。由于外部while永不退出,因此单击“播放”按钮后,您将永远不会返回真正的GTK主循环。

正确的GTK程序不像some_stuff()那样重新实现主循环,正是为了避免这些问题,并且在没有任何事情发生时也避免忙循环。 while gtk.events_pending(): gtk.main_iteration()成语应该非常谨慎地使用,只有在绝对必要时才会使用(更新进度条)。

答案 1 :(得分:1)

根据对其他答案的评论将此答案添加为答案(因为评论有点长)。让我们假设一个游戏迭代很快,你可以在gtk主线程中做一个而不会伤害UI。

  1. 制作一个运行游戏一次迭代的功能(首先你可以打印一些东西)。该函数应该是“空闲处理程序回调”(见下文)。它应该返回True,除非游戏暂停或停止:在这种情况下它应该返回False(意味着不应该再次调用该函数)。
  2. 在Play()中为迭代函数添加idle handler
  3. 在Pause()中,更新暂停的变量,如果取消暂停,还会添加一个闲置的处理程序,如Play()
  4. 这样,迭代函数会在调用Play后继续调用(但UI也会更新)。暂停后,迭代函数仍然被调用一次,但它将返回False并且不会再次调用。