在Python MDI应用程序中结束GTK +主循环(Ending the GTK+ main loop in an Python MDI application)

我正在尝试编写一个由各种窗口组成的应用程序(例如,通用消息对话框,登录对话框,主界面等),并且无法调用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()

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


DIFF On @ DonQuestion的建议:

- self.destroy() + self.emit('destroy') - App() + app = App()

这没有解决问题......


更新接受@jku的答案,但也看到我自己的答案额外信息......

I am trying to code an application that consists of various windows (e.g., generic message dialog, login dialog, main interface, etc.) and am having trouble getting the gtk.main_quit function to be called: either I get a complaint about the call being outside the main loop, or the function doesn't get called at all.

I am a newbie to both Python and GTK+, but my best guess as to how to get this to work is to have a "root" window, which is just a placeholder that is never seen, but controls the application's GTK+ loop. My code, so far, is as follows:

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

The nuke function never gets called, despite the explicit calls to destroy.


DIFF On @DonQuestion's advice:

- self.destroy() + self.emit('destroy') - App() + app = App()

This didn't solve the problem...


UPDATE Accepted @jku's answer, but also see my own answer for extra information...

最满意答案

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

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

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

First, there is a bit of a test problem with the code: You call Gtk.main_quit() from the App initialization: this happens before main loop is even running so signals probably won't work.

Second, you'll probably get a warning on destroy(): 'destroy' handler only takes two arguments (self plus one) but yours has three...

Also with regards to your comment about control flow: You don't need a Window to get signals as they're a GObject feature. And for your testing needs you could write a App.test_except() function and use glib.idle_add (self.test_except) in the object initialization -- this way test_except() is called when main loop is running.

在Python MDI应用程序中结束GTK +主循环(Ending the GTK+ main loop in an Python MDI application)

我正在尝试编写一个由各种窗口组成的应用程序(例如,通用消息对话框,登录对话框,主界面等),并且无法调用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()

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


DIFF On @ DonQuestion的建议:

- self.destroy() + self.emit('destroy') - App() + app = App()

这没有解决问题......


更新接受@jku的答案,但也看到我自己的答案额外信息......

I am trying to code an application that consists of various windows (e.g., generic message dialog, login dialog, main interface, etc.) and am having trouble getting the gtk.main_quit function to be called: either I get a complaint about the call being outside the main loop, or the function doesn't get called at all.

I am a newbie to both Python and GTK+, but my best guess as to how to get this to work is to have a "root" window, which is just a placeholder that is never seen, but controls the application's GTK+ loop. My code, so far, is as follows:

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

The nuke function never gets called, despite the explicit calls to destroy.


DIFF On @DonQuestion's advice:

- self.destroy() + self.emit('destroy') - App() + app = App()

This didn't solve the problem...


UPDATE Accepted @jku's answer, but also see my own answer for extra information...

最满意答案

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

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

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

First, there is a bit of a test problem with the code: You call Gtk.main_quit() from the App initialization: this happens before main loop is even running so signals probably won't work.

Second, you'll probably get a warning on destroy(): 'destroy' handler only takes two arguments (self plus one) but yours has three...

Also with regards to your comment about control flow: You don't need a Window to get signals as they're a GObject feature. And for your testing needs you could write a App.test_except() function and use glib.idle_add (self.test_except) in the object initialization -- this way test_except() is called when main loop is running.