Class Calculator

  • All Implemented Interfaces:
    java.awt.event.ActionListener, java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable, java.util.EventListener, javax.accessibility.Accessible

    public class Calculator
    extends javax.swing.JPanel
    implements java.awt.event.ActionListener
    Calculator is a component that can do simple arithmetic calculation. Since it extends JPanel, you can use it at any place in your application.

    To make it more flexible, the Calculator has no text field to display the result. You can create your own JTextField or JLabel to display the result. Here is a simple example to create a text field and associate it with Calculator.

    
     final JTextField textField = new JTextField();
     textField.setColumns(20);
     textField.setHorizontalAlignment(JTextField.TRAILING);
     Calculator calculator = new Calculator();
     calculator.registerKeyboardActions(textField, JComponent.WHEN_FOCUSED);
     calculator.addPropertyChangeListener(Calculator.PROPERTY_DISPLAY_TEXT, new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent evt) {
             textField.setText("" + evt.getNewValue());
         }
     });
     calculator.clear();
     
    With the code above, user can type in directly into text field and do the calculation. If you just want to display the result and don't mind if the text field accepts keyboard input, you don't need to call registerKeyboardActions method.

    All numeric and operator keys work as expected. Here are a few special keys that worth mentioning

    • 'C', 'c' or ESC to clear current result
    • '!' to make current displayed number from positive to negative (or from negative to positive)
    • ENTER is equivalent to '='..

    Another interesting way to use Calculator is to use it without using GUI.

    
     Calculator calculator = new Calculator();
     calculator.input('1');
     calculator.input('0');
     calculator.input('*');
     calculator.input('2');
     calculator.input('4');
     calculator.input('=');
     System.out.println("10 * 24 = " + calculator.getDisplayText());
     
    The print out will be "10 * 24 = 240".

    There are several methods you can use to get internal state of the Calculator.

    • getDisplayText(): to get the result that should be displayed. Please note, this method return a string.
    • getResult(): to get the last calculated result. This method returns a double value.
    • getOperator(): to get the current operator
    • isOverflow(): to check if there is an overflow. Usually if you try to divide by zero, you will get an overflow.
    See Also:
    Serialized Form
    • Nested Class Summary

      • Nested classes/interfaces inherited from class javax.swing.JPanel

        javax.swing.JPanel.AccessibleJPanel
      • Nested classes/interfaces inherited from class javax.swing.JComponent

        javax.swing.JComponent.AccessibleJComponent
      • Nested classes/interfaces inherited from class java.awt.Container

        java.awt.Container.AccessibleAWTContainer
      • Nested classes/interfaces inherited from class java.awt.Component

        java.awt.Component.AccessibleAWTComponent, java.awt.Component.BaselineResizeBehavior, java.awt.Component.BltBufferStrategy, java.awt.Component.FlipBufferStrategy
    • Constructor Summary

      Constructors 
      Constructor Description
      Calculator()
      Creates a Calculator.
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void actionPerformed​(java.awt.event.ActionEvent e)  
      protected void beep()  
      void clear()
      Clears the internal state and reset the calculator.
      void commit()
      Calculates the pending calculation.
      protected void configureNumberFormat()
      Configures the number format for displaying purpose.
      protected javax.swing.AbstractButton createButton​(java.lang.String text)
      Creates the button that is used in the Calculator.
      protected javax.swing.AbstractButton createButton​(java.lang.String text, javax.swing.Icon icon)
      Creates the button that is used in the Calculator.
      protected void fakePressButton​(javax.swing.AbstractButton button)
      Press the button.
      int getButtonGap()
      Gets the gap between buttons.
      int getButtonHeight()
      Gets the button height.
      int getButtonWidth()
      Gets the button width.
      java.text.NumberFormat getDisplayFormat()
      Gets the display format for the number.
      java.lang.String getDisplayText()
      Gets the display text.
      int getOperator()
      Gets the current operator.
      double getResult()
      Gets the last calculated result.
      protected void initComponents()  
      void input​(char c)
      Inputs a char to the calculator.
      protected boolean isCellEditor()
      If this method return true, ENTER and ESCAPE key will be registered.
      static boolean isEnterOrEqual​(java.awt.event.KeyEvent keyEvent)
      Checks if the key event a key event for enter.
      static boolean isOperator​(java.awt.event.KeyEvent keyEvent)
      Checks if the key event a key event for operators.
      boolean isOverflow()
      Checks if the calculator is in overflow state.
      boolean isResultCalculated()
      Get the flag indicating if the result was calculated at least once.
      static boolean isValidKeyEvent​(java.awt.event.KeyEvent keyEvent)
      Checks if the key event a valid key event that can be accepted by the Calculator.
      static void main​(java.lang.String[] args)  
      void registerKeyboardActions​(javax.swing.JComponent component, int condition)
      Registers necessary keyboard actions onto the component.
      void setButtonGap​(int buttonGap)  
      void setButtonHeight​(int buttonHeight)
      Sets the button height.
      void setButtonWidth​(int buttonWidth)
      Sets the button width.
      void setDisplayFormat​(java.text.NumberFormat displayFormat)
      Sets the display format for the number.
      void setDisplayText​(java.lang.String displayText)
      Sets the display text and fire property change event on property named PROPERTY_DISPLAY_TEXT.
      void setInitialValue​(java.lang.String value)  
      void setLocale​(java.util.Locale l)  
      void setOperator​(int operator)
      Sets the operator and fire property change event on property named PROPERTY_OPERATOR.
      void setOverflow​(boolean overflow)
      Sets the overflow flag.
      void setResultCalculated​(boolean resultCalculated)
      Set the flag indicating if the result was calculated at least once.
      void unregisterKeyboardActions​(javax.swing.JComponent component)
      Unregisters the keyboard actions you registered using registerKeyboardActions(javax.swing.JComponent, int).
      void updateResult()
      Update the result as if the equal was pressed.
      • Methods inherited from class javax.swing.JPanel

        getAccessibleContext, getUI, getUIClassID, paramString, setUI, updateUI
      • Methods inherited from class javax.swing.JComponent

        addAncestorListener, addNotify, addVetoableChangeListener, computeVisibleRect, contains, createToolTip, disable, enable, firePropertyChange, firePropertyChange, firePropertyChange, fireVetoableChange, getActionForKeyStroke, getActionMap, getAlignmentX, getAlignmentY, getAncestorListeners, getAutoscrolls, getBaseline, getBaselineResizeBehavior, getBorder, getBounds, getClientProperty, getComponentGraphics, getComponentPopupMenu, getConditionForKeyStroke, getDebugGraphicsOptions, getDefaultLocale, getFontMetrics, getGraphics, getHeight, getInheritsPopupMenu, getInputMap, getInputMap, getInputVerifier, getInsets, getInsets, getListeners, getLocation, getMaximumSize, getMinimumSize, getNextFocusableComponent, getPopupLocation, getPreferredSize, getRegisteredKeyStrokes, getRootPane, getSize, getToolTipLocation, getToolTipText, getToolTipText, getTopLevelAncestor, getTransferHandler, getVerifyInputWhenFocusTarget, getVetoableChangeListeners, getVisibleRect, getWidth, getX, getY, grabFocus, hide, isDoubleBuffered, isLightweightComponent, isManagingFocus, isOpaque, isOptimizedDrawingEnabled, isPaintingForPrint, isPaintingOrigin, isPaintingTile, isRequestFocusEnabled, isValidateRoot, paint, paintBorder, paintChildren, paintComponent, paintImmediately, paintImmediately, print, printAll, printBorder, printChildren, printComponent, processComponentKeyEvent, processKeyBinding, processKeyEvent, processMouseEvent, processMouseMotionEvent, putClientProperty, registerKeyboardAction, registerKeyboardAction, removeAncestorListener, removeNotify, removeVetoableChangeListener, repaint, repaint, requestDefaultFocus, requestFocus, requestFocus, requestFocusInWindow, requestFocusInWindow, resetKeyboardActions, reshape, revalidate, scrollRectToVisible, setActionMap, setAlignmentX, setAlignmentY, setAutoscrolls, setBackground, setBorder, setComponentPopupMenu, setDebugGraphicsOptions, setDefaultLocale, setDoubleBuffered, setEnabled, setFocusTraversalKeys, setFont, setForeground, setInheritsPopupMenu, setInputMap, setInputVerifier, setMaximumSize, setMinimumSize, setNextFocusableComponent, setOpaque, setPreferredSize, setRequestFocusEnabled, setToolTipText, setTransferHandler, setUI, setVerifyInputWhenFocusTarget, setVisible, unregisterKeyboardAction, update
      • Methods inherited from class java.awt.Container

        add, add, add, add, add, addContainerListener, addImpl, addPropertyChangeListener, addPropertyChangeListener, applyComponentOrientation, areFocusTraversalKeysSet, countComponents, deliverEvent, doLayout, findComponentAt, findComponentAt, getComponent, getComponentAt, getComponentAt, getComponentCount, getComponents, getComponentZOrder, getContainerListeners, getFocusTraversalKeys, getFocusTraversalPolicy, getLayout, getMousePosition, insets, invalidate, isAncestorOf, isFocusCycleRoot, isFocusCycleRoot, isFocusTraversalPolicyProvider, isFocusTraversalPolicySet, layout, list, list, locate, minimumSize, paintComponents, preferredSize, printComponents, processContainerEvent, processEvent, remove, remove, removeAll, removeContainerListener, setComponentZOrder, setFocusCycleRoot, setFocusTraversalPolicy, setFocusTraversalPolicyProvider, setLayout, transferFocusDownCycle, validate, validateTree
      • Methods inherited from class java.awt.Component

        action, add, addComponentListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addInputMethodListener, addKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, bounds, checkImage, checkImage, coalesceEvents, contains, createImage, createImage, createVolatileImage, createVolatileImage, disableEvents, dispatchEvent, enable, enableEvents, enableInputMethods, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, getBackground, getBounds, getColorModel, getComponentListeners, getComponentOrientation, getCursor, getDropTarget, getFocusCycleRootAncestor, getFocusListeners, getFocusTraversalKeysEnabled, getFont, getForeground, getGraphicsConfiguration, getHierarchyBoundsListeners, getHierarchyListeners, getIgnoreRepaint, getInputContext, getInputMethodListeners, getInputMethodRequests, getKeyListeners, getLocale, getLocation, getLocationOnScreen, getMouseListeners, getMouseMotionListeners, getMousePosition, getMouseWheelListeners, getName, getParent, getPropertyChangeListeners, getPropertyChangeListeners, getSize, getToolkit, getTreeLock, gotFocus, handleEvent, hasFocus, imageUpdate, inside, isBackgroundSet, isCursorSet, isDisplayable, isEnabled, isFocusable, isFocusOwner, isFocusTraversable, isFontSet, isForegroundSet, isLightweight, isMaximumSizeSet, isMinimumSizeSet, isPreferredSizeSet, isShowing, isValid, isVisible, keyDown, keyUp, list, list, list, location, lostFocus, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, paintAll, postEvent, prepareImage, prepareImage, processComponentEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processMouseWheelEvent, remove, removeComponentListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removePropertyChangeListener, removePropertyChangeListener, repaint, repaint, repaint, requestFocus, requestFocus, requestFocusInWindow, resize, resize, setBounds, setBounds, setComponentOrientation, setCursor, setDropTarget, setFocusable, setFocusTraversalKeysEnabled, setIgnoreRepaint, setLocation, setLocation, setMixingCutoutShape, setName, setSize, setSize, show, show, size, toString, transferFocus, transferFocusBackward, transferFocusUpCycle
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Constructor Detail

      • Calculator

        public Calculator()
        Creates a Calculator.
    • Method Detail

      • setLocale

        public void setLocale​(java.util.Locale l)
        Overrides:
        setLocale in class java.awt.Component
      • configureNumberFormat

        protected void configureNumberFormat()
        Configures the number format for displaying purpose.
      • isValidKeyEvent

        public static boolean isValidKeyEvent​(java.awt.event.KeyEvent keyEvent)
        Checks if the key event a valid key event that can be accepted by the Calculator.
        Parameters:
        keyEvent - the key event.
        Returns:
        true if it is a valid key event for the Calculator.
      • isOperator

        public static boolean isOperator​(java.awt.event.KeyEvent keyEvent)
        Checks if the key event a key event for operators. In the other words, if it is CHAR_ADD, CHAR_MINUS, CHAR_MULTIPLY or CHAR_DIVIDE, this method will return true.
        Parameters:
        keyEvent - the key event.
        Returns:
        true if it is a valid key event is an operator.
      • isEnterOrEqual

        public static boolean isEnterOrEqual​(java.awt.event.KeyEvent keyEvent)
        Checks if the key event a key event for enter. In the other words, if it is KeyEvent.VK_ENTER or KeyEvent.VK_EQUALS, this method will return true.
        Parameters:
        keyEvent - the key event.
        Returns:
        true if it is a valid key event is an enter key or an equal key.
      • registerKeyboardActions

        public void registerKeyboardActions​(javax.swing.JComponent component,
                                            int condition)
        Registers necessary keyboard actions onto the component. Usually the component is a JTextField.
        Parameters:
        component - the component where the key input will be taken and passed to the Calculator.
        condition - the condition as defined in JComponent.registerKeyboardAction(java.awt.event.ActionListener, javax.swing.KeyStroke, int).
      • initComponents

        protected void initComponents()
      • isResultCalculated

        public boolean isResultCalculated()
        Get the flag indicating if the result was calculated at least once.
        Returns:
        true if the result was calculated at least once. Otherwise false.
      • setResultCalculated

        public void setResultCalculated​(boolean resultCalculated)
        Set the flag indicating if the result was calculated at least once.
        Parameters:
        resultCalculated - the flag
      • createButton

        protected javax.swing.AbstractButton createButton​(java.lang.String text)
        Creates the button that is used in the Calculator. By default, it will create a JideButton. Here is the code. You can override it to create your own button. This method is used to create all buttons except the backspace and the +/- button. So if you want to override it, it's better to override createButton(String, javax.swing.Icon) method.
        Parameters:
        text - the text on the button.
        Returns:
        the button.
      • createButton

        protected javax.swing.AbstractButton createButton​(java.lang.String text,
                                                          javax.swing.Icon icon)
        Creates the button that is used in the Calculator. By default, it will create a JideButton. Here is the code. You can override it to create your own button.
        
         AbstractButton button = new JideButton(text, icon);
         button.setOpaque(true);
         button.setContentAreaFilled(true);
         button.setRequestFocusEnabled(false);
         button.setFocusable(false);
         button.addActionListener(this);
         return button;
         
        Parameters:
        text - the text on the button.
        icon - the icon on the button.
        Returns:
        the button.
      • isOverflow

        public boolean isOverflow()
        Checks if the calculator is in overflow state.
        Returns:
        true if overflow.
      • setOverflow

        public void setOverflow​(boolean overflow)
        Sets the overflow flag.
        Parameters:
        overflow - the overflow flag.
      • input

        public void input​(char c)
        Inputs a char to the calculator. Please note, not all chars are acceptable. Valid chars are defined in Calculator class as CHAR_XXX constants.
        Parameters:
        c - the char input char.
      • beep

        protected void beep()
      • updateResult

        public void updateResult()
        Update the result as if the equal was pressed. This method can be used while Enter key is pressed and you need keep the calculated result.
      • clear

        public void clear()
        Clears the internal state and reset the calculator.
      • getResult

        public double getResult()
        Gets the last calculated result.
        Returns:
        the last calculated result.
      • getDisplayText

        public java.lang.String getDisplayText()
        Gets the display text.
        Returns:
        the display text.
      • setDisplayText

        public void setDisplayText​(java.lang.String displayText)
        Sets the display text and fire property change event on property named PROPERTY_DISPLAY_TEXT.
        Parameters:
        displayText - the displayed text.
      • getOperator

        public int getOperator()
        Gets the current operator.
        Returns:
        the current operator.
      • setOperator

        public void setOperator​(int operator)
        Sets the operator and fire property change event on property named PROPERTY_OPERATOR.
        Parameters:
        operator - the operator.
      • actionPerformed

        public void actionPerformed​(java.awt.event.ActionEvent e)
        Specified by:
        actionPerformed in interface java.awt.event.ActionListener
      • fakePressButton

        protected void fakePressButton​(javax.swing.AbstractButton button)
        Press the button. By default, we will trigger the action directly on this button. However subclass can override it to call doClick to mimic the user pressing the button.
        Parameters:
        button - the button
      • getDisplayFormat

        public java.text.NumberFormat getDisplayFormat()
        Gets the display format for the number.
        Returns:
        the display format for the number.
      • setDisplayFormat

        public void setDisplayFormat​(java.text.NumberFormat displayFormat)
        Sets the display format for the number.
        Parameters:
        displayFormat - the display format.
      • commit

        public void commit()
        Calculates the pending calculation. If the Calculator has both operations and a valid operator, this method will do the calculation and set the display text and result.
      • getButtonWidth

        public int getButtonWidth()
        Gets the button width.
        Returns:
        the button width.
      • setButtonWidth

        public void setButtonWidth​(int buttonWidth)
        Sets the button width.
        Parameters:
        buttonWidth - the new button width.
      • getButtonHeight

        public int getButtonHeight()
        Gets the button height.
        Returns:
        the button height.
      • setButtonHeight

        public void setButtonHeight​(int buttonHeight)
        Sets the button height.
        Parameters:
        buttonHeight - the new button height.
      • getButtonGap

        public int getButtonGap()
        Gets the gap between buttons. Default is 2.
        Returns:
        the gap between buttons.
      • setButtonGap

        public void setButtonGap​(int buttonGap)
      • isCellEditor

        protected boolean isCellEditor()
        If this method return true, ENTER and ESCAPE key will be registered. Otherwise they will not be. The reason we do so because the two keys are conflicted with keys in JTable.
        Returns:
        true or false.
      • setInitialValue

        public void setInitialValue​(java.lang.String value)
      • main

        public static void main​(java.lang.String[] args)