2013-06-03 55 views
0

我的程序有什麼問題?它工作正常,直到它試圖顯示對話框,然後它segfaults。Gtk MessageDialog導致段錯誤(PYGObject)

請原諒我,如果解決方案很明顯,這只是我的第二個GTK +程序。

import time, threading 
from sys import exit 
from gi.repository import Gtk, GObject 


def run_core_engine(): 
    time.sleep(2) 
    window.switchToMainFrame() 
    time.sleep(2.5) 
    window.failDialog("The window said hello") 


class CoreThread(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 
     self.daemon = True 
     super(CoreThread, self).start() 
    def run(self): 
     run_core_engine() 


class GettingInfoFrame(Gtk.Frame): 
    def __init__(self): 
     Gtk.Frame.__init__(self) 
     self.connect("delete-event", Gtk.main_quit) 
     self.set_shadow_type(Gtk.ShadowType.NONE) 
     self.set_border_width(45) 

     vbox = Gtk.VBox(spacing=10) 
     hbox = Gtk.HBox(spacing=10) 

     text = Gtk.Label() 
     text.set_markup("<b><big>Doing stuff...</big></b>") 
     self.spinner = Gtk.Spinner() 
     self.spinner.set_size_request(30, 30) 
     self.spinner.start() 

     hbox.pack_start(text, True, True, 10) 
     hbox.pack_start(self.spinner, True, True, 10) 
     vbox.pack_start(hbox, True, True, 10) 

     self.add(vbox) 


class TheMainFrame(Gtk.Frame): 
    def __init__(self): 
     Gtk.Frame.__init__(self) 
     self.set_shadow_type(Gtk.ShadowType.NONE) 
     self.set_border_width(150) 

     label = Gtk.Label("Hello") 
     box = Gtk.VBox() 
     box.pack_start(label, True, True, 0) 
     self.add(box) 


class Window(Gtk.Window): 
    def __init__(self): 
     ## Setup Main Window 
     Gtk.Window.__init__(self, title="Fred the window") 
     self.connect("delete-event", Gtk.main_quit) 
     self.set_resizable(False) 

     self.gettingInfoFrame = GettingInfoFrame() 
     self.add(self.gettingInfoFrame) 

    def switchToMainFrame(self): 
     print("Displaying information in window") 
     self.theMainFrame = TheMainFrame() 
     self.remove(self.get_child()) 
     self.add(self.theMainFrame) 
     self.show_all() 

    def failDialog(self, message): 
     dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, 
      Gtk.ButtonsType.OK, "INFO:") 
     dialog.format_secondary_text(message) 
     dialog.run() **# <-- Where the error occurs** 

     Gtk.main_quit() 


GObject.threads_init() 

core_thread = CoreThread() 

window = Window() 
window.show_all() 

Gtk.main() 

錯誤行話:在窗口

顯示信息

(2ndgtk +的.py:32073):GTK的WARNING **:GtkMessageDialog 0x7ff51400a040: 插件試圖內部的GtkWidget gtk_widget_get_width: :get_width 執行。應該只是調用 GTK_WIDGET_GET_CLASS(小工具) - > get_width,而不是直接使用 gtk_widget_get_width

(2ndgtk +的.py:32073):GTK的WARNING **:GtkBox 0x7ff514004080:小部件 試圖裏面的GtkWidget gtk_widget_get_width :: get_width 實施。應該只是調用 GTK_WIDGET_GET_CLASS(小工具) - > get_width,而不是直接使用 gtk_widget_get_width

(2ndgtk +的.py:32073):GTK的WARNING **:GtkButtonBox 0x2170620:小部件 試圖裏面的GtkWidget gtk_widget_get_width :: get_width 實施。應該只是調用 GTK_WIDGET_GET_CLASS(小工具) - > get_width,而不是直接使用 gtk_widget_get_width

(2ndgtk +的.py:32073):GTK的WARNING **:GtkButton上0x7ff514010050:小部件 試圖裏面的GtkWidget gtk_widget_get_height :: get_height 實施。應該只是調用 GTK_WIDGET_GET_CLASS(小工具) - > get_height,而不是直接使用 gtk_widget_get_height

(2ndgtk +的.py:32073):GTK的WARNING **:GtkAlignment 0x7ff514014070: 插件試圖裏面的GtkWidget
gtk_widget_get_height :: get_height實現。應該只是調用 GTK_WIDGET_GET_CLASS(小工具) - > get_height,而不是直接使用 gtk_widget_get_height

(2ndgtk +的.py:32073):GTK的WARNING **:GtkBox 0x7ff514004320:小部件 試圖裏面的GtkWidget gtk_widget_get_height :: get_height 實施。應該只是調用 GTK_WIDGET_GET_CLASS(小工具) - > get_height,而不是直接使用 gtk_widget_get_height

(2ndgtk +的.py:32073):GTK的WARNING **:GtkLabel的0x22a2ac0:小工具試圖 裏面的GtkWidget gtk_widget_get_height :: get_height 實施。應該只是調用 GTK_WIDGET_GET_CLASS(小工具) - > get_height,而不是直接使用 gtk_widget_get_height分段故障

回答

1

我想通了。問題是直接調用「window.failDialog」而不是使用GLib.idle_add。 我添加了一些其他細微的變化。

這是新代碼:

import time, threading 
from sys import exit 
from gi.repository import Gtk, GObject, GLib 


def run_core_engine(): 
    time.sleep(2) 
    window.switchToMainFrame() 
    time.sleep(2.5) 
    GLib.idle_add(window.failDialog, "The window said hello") 


class CoreThread(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 
     self.daemon = True 
     super(CoreThread, self).start() 
    def run(self): 
     run_core_engine() 


class GettingInfoFrame(Gtk.Frame): 
    def __init__(self): 
     Gtk.Frame.__init__(self) 
     self.connect("delete-event", Gtk.main_quit) 
     self.set_shadow_type(Gtk.ShadowType.NONE) 
     self.set_border_width(45) 

     vbox = Gtk.VBox(spacing=10) 
     hbox = Gtk.HBox(spacing=10) 

     text = Gtk.Label() 
     text.set_markup("<b><big>Doing stuff...</big></b>") 
     self.spinner = Gtk.Spinner() 
     self.spinner.set_size_request(30, 30) 
     self.spinner.start() 

     hbox.pack_start(text, True, True, 10) 
     hbox.pack_start(self.spinner, True, True, 10) 
     vbox.pack_start(hbox, True, True, 10) 

     self.add(vbox) 


class TheMainFrame(Gtk.Frame): 
    def __init__(self): 
     Gtk.Frame.__init__(self) 
     self.set_shadow_type(Gtk.ShadowType.NONE) 
     self.set_border_width(150) 

     label = Gtk.Label("Hello") 
     box = Gtk.VBox() 
     box.pack_start(label, True, True, 0) 
     self.add(box) 


class Window(Gtk.Window): 
    def __init__(self): 
     ## Setup Main Window 
     Gtk.Window.__init__(self, title="Fred the window") 
     self.connect("delete-event", Gtk.main_quit) 
     self.set_resizable(False) 

     self.gettingInfoFrame = GettingInfoFrame() 
     self.add(self.gettingInfoFrame) 

    def switchToMainFrame(self): 
     print("Displaying information in window") 
     self.theMainFrame = TheMainFrame() 
     self.remove(self.get_child()) 
     self.add(self.theMainFrame) 
     self.show_all() 

    def failDialog(self, errorMessage): 
     dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO, 
      Gtk.ButtonsType.OK, "INFO:") 
     dialog.format_secondary_text(errorMessage) 
     dialog.run() 

     Gtk.main_quit() 


GObject.threads_init() 

core_thread = CoreThread() 

window = Window() 
window.show_all() 

Gtk.main() 
+0

是的,GTK +不是線程安全的,因此所有GUI代碼必須在主線程中運行。正如你所說的,使用idle_add是解決這個問題的一種方法。另請參閱:https://wiki.gnome.org/Projects/PyGObject/Threading –