Introduction

You want to ask the user a question, but yes/no/ok/cancel doesn't fit your needs. This makes it easy to get a single-button response from the user to an arbitrary question.

What Objects are Involved

Just wx.Dialog and your favourite event binding technique.

Process Overview

Usage:

   1 import QuestionDialog
   2 
   3 ...
   4     result = QuestionDialog.questionDialog('Do you like apples or oranges?', buttons=['Apples', 'Oranges', wx.ID_CANCEL])
   5     if result == 'Apples':
   6         print 'Yum!'
   7     elif result == 'Oranges':
   8         print 'Yuck!'
   9     elif result == wx.ID_CANCEL:
  10         print 'Eat more fruit!'
  11     else:
  12         print 'Answer the question!'

Code Sample

   1 """ Dialog to ask a model question, with coder-specified list of buttons. 
   2 """
   3 
   4 import wx
   5 from utils import curry, dropArgs
   6 from wx.lib.evtmgr import eventManager
   7 
   8 class ModalQuestion(wx.Dialog):
   9     """ Ask a question.
  10 
  11     Modal return value will be the index into the list of buttons.  Buttons can be specified
  12     either as strings or as IDs.
  13     """
  14 
  15     def __init__(self, parent, message, buttons, **kw):
  16         wx.Dialog.__init__(self, parent, **kw)
  17 
  18         topSizer = wx.BoxSizer(orient=wx.VERTICAL)
  19         self.SetSizer(topSizer)
  20 
  21         topSizer.Add(wx.StaticText(self, label=message), flag=wx.ALIGN_CENTRE|wx.ALL, border=5)
  22 
  23         line = wx.StaticLine(self, size=(20, -1), style=wx.LI_HORIZONTAL)
  24         topSizer.Add(line, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, border=5)
  25 
  26         buttonSizer = wx.BoxSizer(orient=wx.HORIZONTAL)
  27         topSizer.Add(buttonSizer, flag=wx.ALIGN_CENTRE)
  28 
  29         for i, button in enumerate(buttons):
  30             if isinstance(button, (int, long)):
  31                 b = wx.Button(self, id=button)
  32             else:
  33                 b = wx.Button(self, label=button)
  34 
  35             eventManager.Register(dropArgs(curry(self.EndModal, i)), wx.EVT_BUTTON, b)
  36             buttonSizer.Add(b, flag=wx.ALL, border=5)
  37 
  38         self.Fit()
  39 
  40 def questionDialog(message, buttons=[wx.ID_OK, wx.ID_CANCEL], caption=''):
  41     """ Ask a question.
  42 
  43     Return value will be the button the user clicked, in whatever form it was specified.
  44     Allowable button specifications are strings or wxIDs of stock buttons.
  45 
  46     If the user clicks the 'x' close button in the corner, the return value will be None.
  47     """
  48 
  49     dlg = ModalQuestion(None, message, buttons, title=caption)
  50     try:
  51         return buttons[dlg.ShowModal()]
  52     except IndexError:
  53         return None
  54 
  55 class curry(object):
  56     """Taken from the Python Cookbook, this class provides an easy way to
  57     tie up a function with some default parameters and call it later.
  58     See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549 for more.
  59     """
  60     def __init__(self, func, *args, **kwargs):
  61         self.func = func
  62         self.pending = args[:]
  63         self.kwargs = kwargs
  64 
  65     def __call__(self, *args, **kwargs):
  66         if kwargs and self.kwargs:
  67             kw = self.kwargs.copy()
  68             kw.update(kwargs)
  69         else:
  70             kw = kwargs or self.kwargs
  71         return self.func(*(self.pending + args), **kw)
  72 
  73 class dropArgs(object):
  74     """ Same as curry, but once the function is built, further args are ignored. """
  75 
  76     def __init__(self, func, *args, **kwargs):
  77         self.func = func
  78         self.args = args[:]
  79         self.kwargs = kwargs
  80 
  81     def __call__(self, *args, **kwargs):
  82         return self.func(*self.args, **self.kwargs)

Comments

If you prefer, use b.Bind rather than eventManager.Register.

Also, you can cut out curry and dropArgs and build the button callbacks the hard way if you want. I have them in a utilities module and just import them anyway.

GenericMessageDialog (last edited 2008-03-11 10:50:25 by localhost)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.