Simple, versatile and re-usable entry dialog (sometimes referred to as input dialog) in PyGTK

前端 未结 3 465
天涯浪人
天涯浪人 2020-12-11 18:57

I am searching for a simple dialog with a text entry widget asking the user for some input. The dialog should be easy to run (like the gtk.MessageDialog variant

相关标签:
3条回答
  • 2020-12-11 19:22

    Based on an example I found (thanks Ardoris!), I came up with a dialog subclass... hope it helps someone out there!

    #!/usr/bin/env python
    import gtk
    class EntryDialog(gtk.MessageDialog):
        def __init__(self, *args, **kwargs):
            '''
            Creates a new EntryDialog. Takes all the arguments of the usual
            MessageDialog constructor plus one optional named argument 
            "default_value" to specify the initial contents of the entry.
            '''
            if 'default_value' in kwargs:
                default_value = kwargs['default_value']
                del kwargs['default_value']
            else:
                default_value = ''
            super(EntryDialog, self).__init__(*args, **kwargs)
            entry = gtk.Entry()        
            entry.set_text(str(default_value))
            entry.connect("activate", 
                          lambda ent, dlg, resp: dlg.response(resp), 
                          self, gtk.RESPONSE_OK)
            self.vbox.pack_end(entry, True, True, 0)
            self.vbox.show_all()
            self.entry = entry
        def set_value(self, text):
            self.entry.set_text(text)
        def run(self):
            result = super(EntryDialog, self).run()
            if result == gtk.RESPONSE_OK:
                text = self.entry.get_text()
            else:
                text = None
            return text
    

    The run() method returns either the text entered in the entry box if the user presses <Enter> or clicks Ok. If Cancel is clicked or <Esc> pressed, the run() method returns None.

    Except for that, the dialog should behave as any other gtk.MessageDialog instance.

    Maybe that is not very general as it assumes you will always have Ok as an option, but that is what I need in 99% of my use cases anyway.

    0 讨论(0)
  • 2020-12-11 19:27

    There isn't one available in GTK+. You've got two options:

    • Create a dialog, pack the Entry and any other content you need (probably the best way in my opinion)
    • Retrieve the content_area of the MessageDialog and append an Entry to it.

    Something along the lines of:

    #!/usr/bin/env python
    
    import gtk
    
    messagedialog = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK, message_format="Hello")
    
    action_area = messagedialog.get_content_area()
    
    entry = gtk.Entry()
    action_area.pack_start(entry)
    
    messagedialog.show_all()
    messagedialog.run()
    messagedialog.destroy()
    

    Though it does probably need more refinement to get the Entry to display nicely.

    0 讨论(0)
  • 2020-12-11 19:30

    Here's the function I wrote, based on the previous answers here. It's a function instead of a class, which means you can use it in one line.

    def get_text(parent, message, default=''):
        """
        Display a dialog with a text entry.
        Returns the text, or None if canceled.
        """
        d = gtk.MessageDialog(parent,
                              gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                              gtk.MESSAGE_QUESTION,
                              gtk.BUTTONS_OK_CANCEL,
                              message)
        entry = gtk.Entry()
        entry.set_text(default)
        entry.show()
        d.vbox.pack_end(entry)
        entry.connect('activate', lambda _: d.response(gtk.RESPONSE_OK))
        d.set_default_response(gtk.RESPONSE_OK)
    
        r = d.run()
        text = entry.get_text().decode('utf8')
        d.destroy()
        if r == gtk.RESPONSE_OK:
            return text
        else:
            return None
    
    0 讨论(0)
提交回复
热议问题