pythonuser-interfacegtkmessagedialog

How to change primary text in gtk messagedialog in python?


I'm creating program in python with gtk as gui using glade. In that program, I have several message dialog. It's simple if I just make many message dialog for every case I have. But, is it possible to just make one message dialog and use it for different case with different text? It's simple actually. I just need to change primary text and show it. But, I don't find a way to change primary text here and here.

Below is a sample code:

from gi.repository import Gtk

def clicked1(widget):
    response = dialog1.run()
    if response == Gtk.ResponseType.OK:
        print 'ok'
    else:
        print 'cancel'
        dialog1.destroy()

def clicked2(widget):
    response = dialog2.run()
    if response == Gtk.ResponseType.OK:
        print 'ok'
    else:
        print 'cancel'
        dialog2.destroy()

def clicked3(widget):
    response = dialog3.run()
    if response == Gtk.ResponseType.OK:
        print 'ok'
    else:
        print 'cancel'
        dialog3.destroy()

builder = Gtk.Builder()
builder.add_from_file('gui.glade')
dialog1 = builder.get_object('dialog1')
dialog2 = builder.get_object('dialog2')
dialog3 = builder.get_object('dialog3')
builder.get_object('button1').connect('clicked', clicked1)
builder.get_object('button2').connect('clicked', clicked2)
builder.get_object('button3').connect('clicked', clicked3)
builder.get_object('window1').show_all()
Gtk.main()

I want to change it to be something like this

from gi.repository import Gtk

def clicked1(widget):
    **dialog.set_text(1)**
    response = dialog.run()
    if response == Gtk.ResponseType.OK:
        print 'ok'
    else:
        print 'cancel'
        dialog.destroy()

def clicked2(widget):
    **dialog.set_text(2)**
    response = dialog.run()
    if response == Gtk.ResponseType.OK:
        print 'ok'
    else:
        print 'cancel'
        dialog.destroy()

def clicked3(widget):
    **dialog.set_text(3)**
    response = dialog.run()
    if response == Gtk.ResponseType.OK:
        print 'ok'
    else:
        print 'cancel'
        dialog.destroy()

builder = Gtk.Builder()
builder.add_from_file('gui.glade')
**dialog = builder.get_object('dialog')**
builder.get_object('button1').connect('clicked', clicked1)
builder.get_object('button2').connect('clicked', clicked2)
builder.get_object('button3').connect('clicked', clicked3)
builder.get_object('window1').show_all()
Gtk.main()

Solution

  • It seems that there is no directly way to refresh text in gtk_message_dialog after initialization, but because a message dialog is combination of boxes, labels, images and buttons, so this is an ugly way to modify/refresh primary/secondary text in a message dialog,

    labels = dialog_info.get_children()[0].get_children()[0].get_children()[1].get_children()

    Full source code of this demo is here:

    #!/usr/bin/env python3
    
    from gi.repository import Gtk
    
    class Handler:
        def __init__(self, builder):
            self.builder = builder
            self.window = builder.get_object('window1')
    
        def run(self):
            self.window.show_all()
            Gtk.main()
    
        def on_app_exit(self, widget, event=None):
            Gtk.main_quit()
    
        def on_button_show_clicked(self, btn):
            dialog_info = self.builder.get_object('messagedialog_info')
            entry = self.builder.get_object('entry1')
            labels = dialog_info.get_children()[0].get_children()[0].get_children()[1].get_children()
            print(labels)
            # labels[0] is the primary label.
            # labels[1] is the seconary label.
            labels[0].set_text(entry.get_text())
    
            response = dialog_info.run()
            print('response: ', response)
            dialog_info.hide()
    
    
    def main():
        builder = Gtk.Builder()
        builder.add_from_file('example.glade')
        handler = Handler(builder)
        builder.connect_signals(handler)
        handler.run()
    
    if __name__ == '__main__':
        main()
    

    and the glade file, 'example.glade':

    <?xml version="1.0" encoding="UTF-8"?>
    <interface>
      <!-- interface-requires gtk+ 3.0 -->
      <object class="GtkMessageDialog" id="messagedialog_info">
        <property name="can_focus">False</property>
        <property name="border_width">5</property>
        <property name="type_hint">dialog</property>
        <property name="skip_taskbar_hint">True</property>
        <property name="buttons">close</property>
        <property name="text" translatable="yes">hello text</property>
        <property name="secondary_text" translatable="yes">hello secondary text.</property>
        <child internal-child="vbox">
          <object class="GtkBox" id="messagedialog-vbox">
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <property name="spacing">2</property>
            <child internal-child="action_area">
              <object class="GtkButtonBox" id="messagedialog-action_area">
                <property name="can_focus">False</property>
                <property name="layout_style">end</property>
                <child>
                  <placeholder/>
                </child>
                <child>
                  <placeholder/>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="pack_type">end</property>
                <property name="position">0</property>
              </packing>
            </child>
          </object>
        </child>
      </object>
      <object class="GtkWindow" id="window1">
        <property name="can_focus">False</property>
        <property name="border_width">5</property>
        <signal name="delete-event" handler="on_app_exit" swapped="no"/>
        <child>
          <object class="GtkBox" id="box1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="valign">center</property>
            <property name="spacing">5</property>
            <child>
              <object class="GtkEntry" id="entry1">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="invisible_char">●</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="button_show">
                <property name="label" translatable="yes">_Show</property>
                <property name="use_action_appearance">False</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="use_action_appearance">False</property>
                <property name="use_underline">True</property>
                <signal name="clicked" handler="on_button_show_clicked" swapped="no"/>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
        </child>
      </object>
    </interface>