I have been teaching myself Python and wanted to create something useful while learning. I am using wxPython to create the interface. The app works if I use the mouse to click the buttons. I've been trying to get it to recognize operation key-ins like addition using the num pad +. It will register the keystrokes but the binding for the event handler to run the operation commands isn't working. I know this isn't the cleanest written code and would also appreciate any advice to clean it. I have the code on github.
https://github.com/BridgeGuy/wxCalculator
The calculator uses RPN similar to an HP48 series calculator and has the display appearance similar to an HP48 as well.

This is the section of code I think is not functioning the way I thought it should for recognizing the operation key-ins. The for loop for buttons1 generates the number pad. The for loop for buttons2 generates the buttons for the calculator operations.

`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)
            b.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress)
    sizer.Add(gsizer2, (6,1),(1,1), wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)
    self.SetSizerAndFit(sizer)

def OnKeyPress(self, event):
    keycode = event.GetKeyCode()
    if keycode == wx.WXK_RETURN or wx.WXK_NUMPAD_ENTER:
        self.enter()

    elif keycode == wx.WXK_ADD or wx.WXK_NUMPAD_ADD:

    self.add()`

It is probably something simple. I just don't have the experience yet to know what it is.
Thanks

Recommended Answers

All 3 Replies

The result of if keycode == foo or bar is probably not what you are expecting. You probably meant if keycode in (foo, bar)

I updated the if statement to:
'if keycode in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):'
and still doesn't recognize the enter key.

I did some more digging and found I may not have the binding correct. I tried moving the binding to when the TextCtrl is created but the binding overrides regular text input into the control. The code in the OP contains my original attempt. I tried a different attempt but regular input stopped functioning.
This is the revised section:
'self.display = wx.TextCtrl(self, -1, style=wx.TE_RIGHT)
self.display.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress)'

I reduced the program to just the display and input.
I'm pretty sure I'm not binding the TextCtrl correctly but I can't figure out how it should be done so it will recognize =, +, -, etc. as operations and not text input in the display.

import wx
import math
from fractions import Fraction

DISP_COLOR = wx.Colour(243, 248, 205) # Yellowish
STACK4 = 0
STACK3 = 0
STACK2 = 0
STACK1 = 0

class MainFrame(wx.Frame):
    '''Main calculator frame'''
    def __init__(self, *args, **kwargs):
        kwargs.setdefault('title', "Feet-Inch Calculator")
        wx.Frame.__init__(self, *args, **kwargs)
        self.calcPanel = CalcPanel(self)
        fsizer = wx.BoxSizer(wx.VERTICAL)
        fsizer.Add(self.calcPanel, 1, wx.EXPAND, 10)
        self.CenterOnScreen()
        self.SetSizerAndFit(fsizer)


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)

        #-------------Display------------------
        self.display4 = wx.StaticText(self, -1, str(STACK4),
                                      style=wx.ALIGN_RIGHT|wx.ST_NO_AUTORESIZE)
        self.display3 = wx.StaticText(self, -1, str(STACK3), 
                                      style=wx.ALIGN_RIGHT|wx.ST_NO_AUTORESIZE)
        self.display2 = wx.StaticText(self, -1, str(STACK2),
                                      style=wx.ALIGN_RIGHT|wx.ST_NO_AUTORESIZE)
        self.display1 = wx.StaticText(self, -1, str(STACK1),
                                      style=wx.ALIGN_RIGHT|wx.ST_NO_AUTORESIZE)
        self.display = wx.TextCtrl(self, -1, style=wx.TE_RIGHT)
        #self.display.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress)
        self.text4 = wx.StaticText(self, -1, "4:")
        self.text3 = wx.StaticText(self, -1, "3:")
        self.text2 = wx.StaticText(self, -1, "2:")
        self.text1 = wx.StaticText(self, -1, "1:")
        sizer.Add(self.text4, (0,0), (1,1), wx.EXPAND|wx.LEFT|wx.TOP, 10)
        sizer.Add(self.text3, (1,0), (1,1), wx.EXPAND|wx.LEFT, 10)
        sizer.Add(self.text2, (2,0), (1,1), wx.EXPAND|wx.LEFT, 10)
        sizer.Add(self.text1, (3,0), (1,1), wx.EXPAND|wx.LEFT, 10)
        sizer.Add(self.display4, (0,1), (1,1), wx.EXPAND|wx.RIGHT|wx.TOP, 10)
        sizer.Add(self.display3, (1,1), (1,1), wx.EXPAND|wx.RIGHT, 10)
        sizer.Add(self.display2, (2,1), (1,1), wx.EXPAND|wx.RIGHT, 10)
        sizer.Add(self.display1, (3,1), (1,1), wx.EXPAND|wx.RIGHT, 10)
        sizer.Add(self.display, (4,0), (1,2), wx.EXPAND|wx.RIGHT|wx.LEFT, 10)
        self.SetSizerAndFit(sizer)

    def OnKeyPress(self, event):
        keycode = event.GetKeyCode()
        if keycode in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
            self.enter()

        elif keycode in (wx.WXK_ADD, wx.WXK_NUMPAD_ADD):
            self.add()

    def enter(self):
        """ enter a new number to the stack"""
        global STACK1, STACK2, STACK3, STACK4
        if self.display.GetValue() != "":
            STACK4 = STACK3
            STACK3 = STACK2
            STACK2 = STACK1
            STACK1 = self.frac_to_decimal()
            self.updateDisplay()
        else:
            STACK4 = STACK3
            STACK3 = STACK2
            STACK2 = STACK1
            STACK1 = 0
            self.updateDisplay()

    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
            self.updateDisplay()                

    def updateDisplay(self):
        """ update display """
        global STACK1, STACK2, STACK3, STACK4
        if self.rbox.GetSelection() == 0:
            S4 = self.fraction_str(STACK4)
            S3 = self.fraction_str(STACK3)
            S2 = self.fraction_str(STACK2)
            S1 = self.fraction_str(STACK1)
        elif self.rbox.GetSelection() == 1:
            S4 = str(STACK4 * 12)
            S3 = str(STACK3 * 12)
            S2 = str(STACK2 * 12)
            S1 = str(STACK1 * 12)
        else:
            S4 = str(STACK4)
            S3 = str(STACK3)
            S2 = str(STACK2)
            S1 = str(STACK1)

        self.display4.SetLabel(S4)
        self.display3.SetLabel(S3)
        self.display2.SetLabel(S2)
        self.display1.SetLabel(S1)
        self.display.SetValue('')
        self.display.SetFocus()                        

if __name__ == '__main__':
    calculator = wx.App(False)
    calc = MainFrame(None)
    calc.Show(True)
    calculator.MainLoop()
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.