Simple, versatile and re-usable entry dialog (some

2019-01-20 10:29发布

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 variants) and as flexible.

There are of course some examples but they are either not flexible enough or too complicated to construct for my taste.

I hate re-inventing the wheel... or a dialog.

3条回答
可以哭但决不认输i
2楼-- · 2019-01-20 11:02

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.

查看更多
一纸荒年 Trace。
3楼-- · 2019-01-20 11:07

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
查看更多
男人必须洒脱
4楼-- · 2019-01-20 11:14

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.

查看更多
登录 后发表回答