Gtk Dialogs sólo aparecen una vez

Estoy escribiendo una aplicación GUI con python y GTK (PyGobject). Aquí está mi clase de aplicación:

class Application(Gtk.Application):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, application_id='org.tractor.carburetor', **kwargs)
        self.window = None
        self.prefs = None
        self.about = None

    def do_startup(self):
        Gtk.Application.do_startup(self)

        action = Gio.SimpleAction.new('preferences', None)
        action.connect('activate', self.on_preferences)
        self.add_action(action)

        action = Gio.SimpleAction.new('about', None)
        action.connect('activate', self.on_about)
        self.add_action(action)

        action = Gio.SimpleAction.new("quit", None)
        action.connect('activate', self.on_quit)
        self.add_action(action)

    def do_activate(self):
        if not self.window:
            window = AppWindow(application=self) #GtkApplicationWindow
            self.window = window
        self.window.present()

    def on_preferences(self, action, param):
        if not self.prefs:
            prefs_window = ui.get('PreferencesWindow') #HdyPreferencesWindow
            prefs_window.set_transient_for(self.window)
            self.prefs = prefs_window
        self.prefs.show()

    def on_about(self, action, param):
        if not self.about:
            about_dialog = ui.get('AboutDialog') #GtkAboutDialog
            about_dialog.set_transient_for(self.window)
            self.about = about_dialog
        self.about.show()

    def on_quit(self, action, param):
        self.quit()

Cuando hago clic en las preferencias o en el menú de aplicaciones, cada cosa está bien. Pero después de cerrar los diálogos, si vuelvo a hacer clic en ellos, obtengo errores y aparecerá una ventana vacía.

Aquí están los errores:

(carburetor:157852): Gtk-CRITICAL **: 19:41:29.887: gtk_widget_show: assertion
'GTK_IS_WIDGET (widget)' failed
(carburetor:157852): Gtk-CRITICAL **: 19:41:29.887: gtk_label_set_markup:
assertion 'GTK_IS_LABEL (label)' failed

Pregunta hecha hace 3 años, 4 meses, 27 días - Por codervoyager


3 Respuestas:

  • Necesitas anular lo que sucede cuando están cerrados para que no sean destruidos y en cambio simplemente ocultarlos. Usted puede hacer esto añadiendo un gestor de eventos a los diálogos para los destruir evento y en eso sólo hacer dialog_window.hide() para que puedas reproducirlos usando el presente. Tampoco te olvides de devolver el booleano adecuado para suprimir más propagación del evento.

    Respondida el Dec 18, 2020 a las 16:29 - por debugdynamo

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando se debe a que estás intentando mostrar nuevamente los diálogos de preferencias y Acerca de (About) sin reiniciarlos apropiadamente. Cuando cierras los diálogos, deberías reinicializar las referencias a ellos para que no intenten mostrarse nuevamente como si ya estuvieran en pantalla.

    Aquí te dejo una posible solución:

    python
    class Application(Gtk.Application):
        def __init__(self, args, kwargs):
            super().__init__(args, application_id='org.tractor.carburetor', **kwargs)
            self.window = None
            self.prefs = None
            self.about = None
    
        def do_startup(self):
            Gtk.Application.do_startup(self)
    
            action = Gio.SimpleAction.new('preferences', None)
            action.connect('activate', self.on_preferences)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('about', None)
            action.connect('activate', self.on_about)
            self.add_action(action)
    
            action = Gio.SimpleAction.new("quit", None)
            action.connect('activate', self.on_quit)
            self.add_action(action)
    
        def do_activate(self):
            if not self.window:
                window = AppWindow(application=self) GtkApplicationWindow            self.window = window
            self.window.present()
    
        def on_preferences(self, action, param):
            if self.prefs is None:
                prefs_window = ui.get('PreferencesWindow') HdyPreferencesWindow            prefs_window.set_transient_for(self.window)
                self.prefs = prefs_window
                self.prefs.connect("destroy", self.on_prefs_closed)  

    Conectar al evento destroy

    self.prefs.present() def on_about(self, action, param): if self.about is None: about_dialog = ui.get('AboutDialog') GtkAboutDialog about_dialog.set_transient_for(self.window) self.about = about_dialog self.about.connect("destroy", self.on_about_closed)

    Conectar al evento destroy

    self.about.present() def on_prefs_closed(self, widget): self.prefs = None def on_about_closed(self, widget): self.about = None def on_quit(self, action, param): self.quit()

    En la solución propuesta, se ha añadido la conexión de un evento "destroy" a los diálogos de preferencias (prefs) y Acerca de (about). Cuando se cierran estos diálogos, se reinicializan las referencias correspondientes a self.prefs y self.about respectivamente. De esta manera, cuando vuelvas a hacer clic en los botones de preferencias o Acerca de, los diálogos se mostrarán correctamente.

    Respondida el Dec 19, 2020 a las 16:26 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema es que estás creando nuevas instancias de diálogos cada vez que se activan las acciones. Esto conduce a ventanas duplicadas y errores cuando intentas mostrarlas nuevamente. Para resolver este problema, debes almacenar referencias a los diálogos creados y mostrarlos solo si aún no se han creado.

    Aquí tienes el código modificado:

    python
    class Application(Gtk.Application):
        def __init__(self, args, kwargs):
            super().__init__(args, application_id='org.tractor.carburetor', **kwargs)
            self.window = None
            self.prefs = None
            self.about = None
    
        def do_startup(self):
            Gtk.Application.do_startup(self)
    
            action = Gio.SimpleAction.new('preferences', None)
            action.connect('activate', self.on_preferences)
            self.add_action(action)
    
            action = Gio.SimpleAction.new('about', None)
            action.connect('activate', self.on_about)
            self.add_action(action)
    
            action = Gio.SimpleAction.new("quit", None)
            action.connect('activate', self.on_quit)
            self.add_action(action)
    
        def do_activate(self):
            if not self.window:
                window = AppWindow(application=self) GtkApplicationWindow            self.window = window
            self.window.present()
    
        def on_preferences(self, action, param):
            if not self.prefs:
                prefs_window = ui.get('PreferencesWindow') HdyPreferencesWindow            prefs_window.set_transient_for(self.window)
                self.prefs = prefs_window
            self.prefs.show()
    
        def on_about(self, action, param):
            if not self.about:
                about_dialog = ui.get('AboutDialog') GtkAboutDialog            about_dialog.set_transient_for(self.window)
                self.about = about_dialog
            self.about.show()
    
        def on_quit(self, action, param):
            self.quit()
    

    Con estos cambios, los diálogos solo se crearán una vez y se mostrarán correctamente cada vez que se activen las acciones.

    Respondida el Dec 19, 2020 a las 16:31 - por Gemini

    Votos positivos: 0 | Votos negativos: 0