Keyboard input for RPN type calculator

I have been teaching myself wxPython. I have a little Python experience as I have taken a couple online classes. I am creating a RPN type calculator that will work with feet and inches. I have the calculator more or less functioning. If I use graphical input (clicking on each button), it will perform the calculation and conversions correctly. What I need help with is getting the calculator to register the operation keys; meaning if I click on the “+” button, it will add the numbers but if I press the “+” key on the keyboard it places a “+” sign in the display and doesn’t perform the function.

As I am still learning, I would appreciate any constructive help. I may have follow questions that hopefully aren’t totally stupid. I’ve included the section of my code below that corresponds to the button creation and binding.

Thank you

class CalcPanel(wx.Panel):

'''Panel containing display, conversion radiobox and buttons'''

def __init__(self, *args, **kwargs):

    wx.Panel.__init__(self, *args, **kwargs)

    sizer = wx.GridBagSizer(3,2)

   #--------------Buttons-----------------

   gsizer1 = wx.GridSizer(5,3,2,2)

    buttons1 = (('7', '8', '9'),

                ('4', '5', '6'),

                ('3', '2', '1'),

                ('C', '0', '.'))

    gsizer2 = wx.GridSizer(5,2,2,2)

    buttons2 = (("Swap", "Del"),

                ("/", "'"),

                ("*", "^"),

                ("-", "sqrt"),

                ("+", "Enter"))

    gsizer1.Add((1,1), 1, wx.EXPAND)

    gsizer1.Add((1,1), 1, wx.EXPAND)

    gsizer1.Add((1,1), 1, wx.EXPAND)

    for row in buttons1:

        for label in row:

            b = wx.Button(self, label=label, size=(40,-1))

            gsizer1.Add(b)

            b.Bind(wx.EVT_BUTTON, self.OnButton)

    sizer.Add(gsizer1, (6,0),(1,1), wx.EXPAND|wx.LEFT|wx.BOTTOM|wx.ALIGN_BOTTOM, 10)

    for row in buttons2:

        for label in row:

            b = wx.Button(self, label=label, size=(60,-1))

            gsizer2.Add(b)

            b.Bind(wx.EVT_BUTTON, self.OnButton)

    sizer.Add(gsizer2, (6,1),(1,1), wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)

    self.SetSizerAndFit(sizer)

def OnButton(self, event):

    #Get title of clicked button

    global STACK1, STACK2, STACK3, STACK4, STATE, TEMP_NUM

    label = event.GetEventObject().GetLabel()

    if label == 'Enter':

        self.enter()

    elif label == '+':

        self.add()

    elif label == '-':

        self.sub()

    elif label == '/':

        self.div()

    elif label == '*':

        self.mult()

    elif label == 'sqrt':

        self.sqrt()

    elif label == '^':

        self.power()

    elif label == 'Swap':

        self.swap()

    elif label == 'Del':

        self.delete()

    elif label == 'C':

        self.display.SetValue('')

    else:

        self.display.SetValue(self.display.GetValue() + label)

def add(self):

    """ add stack1 and display or contents of stack"""

    global STACK1, STACK2, STACK3, STACK4

    if self.display.GetValue() != "":

        STACK1 = STACK1 + self.frac_to_decimal()

        self.updateDisplay()

    else:

        STACK1 = STACK2 + STACK1

        STACK2 = STACK3

        STACK3 = STACK4

        STACK4 = 0

``

Hi,

···

On 1/28/2015 6:10, Colby Christensen wrote:

I have been teaching myself wxPython. I have a little Python experience as I have taken a couple online classes. I am creating a RPN type calculator that will work with feet and inches. I have the calculator more or less functioning. If I use graphical input (clicking on each button), it will perform the calculation and conversions correctly. What I need help with is getting the calculator to register the operation keys; meaning if I click on the "+" button, it will add the numbers but if I press the "+" key on the keyboard it places a "+" sign in the display and doesn't perform the function.

I think you need to catch e.g. wx.EVT_KEY_DOWN or wx.EVT_CHAR and for certain keys then call the appropriate method in your code.

Maybe Mike's blog post helps you to get going on this:
http://www.blog.pythonlibrary.org/2009/08/29/wxpython-catching-key-and-char-events/

Werner

Having 4 fixed stack locations as variables is a bad idea. Python
supports rich data structures – use them. Just implement a
variable call “stack” that is a list.
Also, for your dispatching, instead of a long list of
if/elif/elif/elif, you might consider using a dictionary:

···

Colby Christensen wrote:

      As I am still learning, I would appreciate any constructive

help. I may have follow questions that hopefully aren’t
totally stupid. I’ve included the section of my code below
that corresponds to the button creation and binding.

` # Create stack``

``    stack = []``

``    # Push on stack.``

``    stack.append( 3 )``

``    # Pop from stack.``

``    val = stack.pop()``

``

``    # So, addition becomes:``

``    stack.append( stack.pop() + stack.pop() )``

`

` self.dispatch = {``

``        'Enter': self.enter,``

``        '+':     self.add,``

            '-':     self.sub,

  ``        '*':     self.mult,

              '/':     self.div,

    ``        'sqrt':  self.sqrt,

                '^':     self.power,

      ``        'Swap':  self.swap,

                  'Del':   self.delete,

        ``        'C':     self.clear``

        ``    }``

        `

        You can create this one at initialization.  Now your

dispatch becomes:

        `    if label in self.dispatch:``

        ``        self.dispatch[label]()``

        ``    else:````

            ``self``.``display``.``SetValue``(``self``.``display``.``GetValue``()`` ``+`` label``)``

`
-- Tim Roberts, Providenza & Boekelheide, Inc.

timr@probo.com

Thanks Werner and Tim for your suggestions. I had forgotten about using key down to catch the key strokes. I also appreciate the suggestions on how to improve my code.