在Python MDI应用程序中结束GTK +主循环

时间:2013-12-12 12:50:23

标签: python gtk pygtk mdi

我正在尝试编写一个由各种窗口组成的应用程序(例如,通用消息对话框,登录对话框,主界面等),并且无法调用gtk.main_quit函数:要么我得到关于呼叫在主循环之外的抱怨,或者根本没有调用该函数。

我是Python和GTK +的新手,但我最好的猜测是如何让它工作的是一个“根”窗口,它只是一个从未见过的占位符,但控制应用程序的GTK +循环。到目前为止,我的代码如下:

import pygtk
pygtk.require("2.0")
import gtk

class App(gtk.Window):
  _exitStatus = 0

  # Generic message box
  def msg(self, title, text, type = gtk.MESSAGE_INFO, buttons = gtk.BUTTONS_OK):
    # Must always have a button
    if buttons == gtk.BUTTONS_NONE:
      buttons = gtk.BUTTONS_OK

    dialog = gtk.MessageDialog(None, 0, type, buttons, title)
    dialog.set_title(title)
    dialog.set_geometry_hints(min_width = 300)
    dialog.set_resizable(False)
    dialog.set_deletable(False)
    dialog.set_position(gtk.WIN_POS_CENTER)
    dialog.set_modal(True)
    dialog.format_secondary_text(text)

    response = dialog.run()
    dialog.destroy()

    return response

  def nuke(self, widget, data):
    gtk.main_quit()
    exit(self._exitStatus)

  def __init__(self):
    super(App, self).__init__()
    self.connect('destroy', self.nuke)

    try:
      raise Exception()
    except:
      self.msg('OMFG!', 'WTF just happened!?', gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE)
      self._exitStatus = 1
      self.destroy()

    if self.msg('OK', 'Everything worked fine') == gtk.RESPONSE_OK:
      self.destroy()

# Let's go!
App()
gtk.main()

nuke函数永远不会被调用,尽管显式调用了destroy


DIFF 关于@ DonQuestion的建议:

- self.destroy()
+ self.emit('destroy')

- App()
+ app = App()

这并没有解决问题...


更新已接受@ jku的回答,但也可以查看我自己的答案以获取更多信息......

2 个答案:

答案 0 :(得分:2)

首先,代码存在一些测试问题:您从App初始化调用Gtk.main_quit():这在主循环运行之前发生,因此信号可能无效。

其次,你可能会在destroy()上收到一个警告:'destroy'处理程序只需要两个参数(self加一个)但是你的有三个......

关于控制流的评论:您不需要Window来获取信号,因为它们是GObject功能。为了满足您的测试需求,您可以编写App.test_except()函数并在对象初始化中使用glib.idle_add (self.test_except) - 这样在主循环运行时会调用test_except()。

答案 1 :(得分:1)

我认为@jku的答案标识了我的密钥错误,因此我已将其标记为已接受,但在玩游戏时,我发现MessageDialog不需要在GTK +循环中运行。我不知道这是否符合设计,但它确实有效!所以,我将我的通用消息对话框分解为它自己的函数,然后将主应用程序完全保存在它自己的类中,它遵循我期望的主循环:

import pygtk
pygtk.require("2.0")
import gtk

def msg(title, text, type = gtk.MESSAGE_INFO, buttons = gtk.BUTTONS_OK):
  # Only allowed OK, Close, Cancel, Yes/No and OK/Cancel buttons
  # Otherwise, default to just OK
  if buttons not in [gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL]:
    buttons = gtk.BUTTONS_OK

  dialog = gtk.MessageDialog(None, 0, type, buttons, title)
  dialog.set_title(title)
  dialog.set_geometry_hints(min_width = 300)
  dialog.set_resizable(False)
  dialog.set_deletable(False)
  dialog.set_position(gtk.WIN_POS_CENTER)
  dialog.set_modal(True)
  dialog.format_secondary_text(text)

  response = dialog.run()
  dialog.destroy()
  return response

class App:
 def __init__(self):
   # Build UI
   # Connect signals
   # Show whatever

 def appQuit(self, widget):
   gtk.main_quit()

 def signalHandler(self, widget, data = None):
   # Handle signal
   # We can call msg here, when the main loop is running

# Load some resource
# We can call msg here, despite not having invoked the main loop
try:
  # Load resource
except:
  msg('OMFG!', 'WTF just happened!?', gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE)
  exit(1)

# n.b., Calls to msg work even without the following code
App()
gtk.main()
exit(0)