How to Create a Calculator With Mechanical Keyboard Buttons in Java Netbeans
In this Java Tutorial we will see How To Create a Calculator With Mechanical Keyboard Look and engaging click animations In Java Using Netbeans.
What We Are Gonna Use In This Project:
- Java Programming Language.- NetBeans Editor.
Project Source Code:
/**
*
* @author 1BestCsharp
*/
public class Calculator3D extends JPanel{
// These variables store the calculator's current state
private String displayText = "0"; // Text shown on calculator screen
private boolean startNewInput = true; // Whether the next digit starts a new number
private String operation = null; // Current math operation (+, -, *, /)
private double firstOperand = 0; // First number in the calculation
private final int MAX_DISPLAY_LENGTH = 12; // Maximum number of digits on display
// Colors used for different parts of the calculator
private final Color buttonColor = new Color(0, 200, 255); // Regular button color (blue)
private final Color operatorButtonColor = new Color(255, 100, 255); // Math operator buttons color (pink)
private final Color equalButtonColor = new Color(100, 255, 100); // Equals button color (green)
private final Color displayBgColor = new Color(15, 15, 26); // Calculator screen background (dark)
private final Color displayTextColor = new Color(240, 240, 240); // Calculator screen text (light)
// Button size and spacing measurements
private final int buttonWidth = 60; // Width of each button
private final int buttonHeight = 50; // Height of each button
private final int buttonDepth = 15; // How "deep" the 3D effect looks
private final int gap = 10; // Space between buttons
// Layout of all calculator buttons in a grid
private final String[][] buttonLabels = {
{"7", "8", "9", "/"}, // First row of buttons
{"4", "5", "6", "*"}, // Second row of buttons
{"1", "2", "3", "-"}, // Third row of buttons
{"0", ".", "C", "+"}, // Fourth row of buttons
{"", "", "", "="} // Fifth row (only equals button)
};
// Variables for button click animation
private String clickedButton = null; // Currently clicked button (if any)
private javax.swing.Timer clickTimer; // Timer to control how long click effect lasts
private final int CLICK_DURATION = 150; // Click effect duration in milliseconds
// Map to store button positions for detecting clicks
private final Map<String, Rectangle> buttonBounds = new HashMap<>();
public Calculator3D(){
// Set calculator size and background color
setPreferredSize(new Dimension(320, 420));
setBackground(new Color(30, 30, 40));
// Create timer that removes click effect after a short time
clickTimer = new javax.swing.Timer(CLICK_DURATION, e -> {
clickedButton = null; // Clear the clicked button
repaint(); // Redraw the calculator
clickTimer.stop(); // Stop the timer until next click
});
// Listen for mouse clicks on the calculator
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// When user clicks, check which button was pressed
handleMousePress(e.getX(), e.getY());
}
});
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// Make lines and edges look smoother
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
// Draw calculator screen at the top
drawDisplay(g2d);
// Draw all calculator buttons below the screen
drawButtons(g2d);
}
// Method to draw the calculator's display screen
private void drawDisplay(Graphics2D g2d){
// Set the size and position of the display screen
int displayHeight = 70;
int margin = 20;
Rectangle2D display = new Rectangle2D.Double(
margin, margin, getWidth() - 2 * margin, displayHeight);
// Fill the display with background color
g2d.setColor(displayBgColor);
g2d.fill(display);
// Draw border around the display
g2d.setStroke(new BasicStroke(2f));
g2d.setColor(new Color(100, 100, 120));
g2d.draw(display);
// Add shadow effect under the display
g2d.setColor(new Color(0, 0, 0, 50));
g2d.fillRect(margin + 3, margin + displayHeight,
getWidth() - 2 * margin, 5);
// Display the calculator's current number (right-aligned)
g2d.setFont(new Font("Monospaced", Font.BOLD, 30));
g2d.setColor(displayTextColor);
// Get text measurements to align properly
FontMetrics fm = g2d.getFontMetrics();
String textToDisplay = displayText;
// If text is too long, show only the last digits
if (textToDisplay.length() > MAX_DISPLAY_LENGTH) {
textToDisplay = textToDisplay.substring(textToDisplay.length() - MAX_DISPLAY_LENGTH);
}
// Calculate position to right-align the text
int textWidth = fm.stringWidth(textToDisplay);
int textX = (getWidth() - margin - 10) - textWidth;
int textY = margin + displayHeight - 20;
// Draw the text on screen
g2d.drawString(textToDisplay, textX, textY);
}
// Method to draw all calculator buttons
private void drawButtons(Graphics2D g2d){
// Starting position for the button grid
int startX = 20;
int startY = 110;
// Clear previous button positions
buttonBounds.clear();
// Loop through each row and column in the button grid
for(int row = 0; row < buttonLabels.length; row++){
for(int col = 0; col < buttonLabels[row].length; col++){
String label = buttonLabels[row][col];
if (label.isEmpty()) continue; // Skip empty slots
// Calculate button position
int x = startX + col * (buttonWidth + gap);
int y = startY + row * (buttonHeight + gap);
// Store button position for detecting clicks later
buttonBounds.put(label, new Rectangle(x, y, buttonWidth, buttonHeight));
// Choose color based on button type
Color buttonBaseColor;
if (label.equals("=")) {
buttonBaseColor = equalButtonColor; // Green for equals
}
else if ("+-*/C".contains(label)) {
buttonBaseColor = operatorButtonColor; // Pink for operators
}
else {
buttonBaseColor = buttonColor; // Blue for numbers
}
// Check if this button is currently being clicked
boolean isClicked = label.equals(clickedButton);
// Draw this button with 3D effect
draw3DButton(
g2d,
x,
y,
buttonWidth,
buttonHeight,
buttonDepth,
label,
buttonBaseColor,
isClicked
);
}
}
}
// Method to draw a single 3D button
private void draw3DButton(Graphics2D g2d, int x, int y, int width, int height,
int depth, String label, Color color, boolean isClicked){
// Save current drawing settings
var originalTransform = g2d.getTransform();
// When clicked, button appears pressed down
int actualDepth = isClicked ? depth / 3 : depth;
int yOffset = isClicked ? depth - actualDepth : 0;
// Draw top face of button (main face)
Color topColor = isClicked ? darken(color, 0.9) : color;
g2d.setColor(topColor);
Rectangle2D topFace = new Rectangle2D.Double(x, y + yOffset, width, height);
g2d.fill(topFace);
// Draw right face of button (side)
Color rightColor = darken(color, 0.7);
g2d.setColor(rightColor);
Path2D rightFace = new Path2D.Double();
rightFace.moveTo(x + width, y + yOffset);
rightFace.lineTo(x + width + actualDepth, y + yOffset + actualDepth);
rightFace.lineTo(x + width + actualDepth, y + yOffset + height + actualDepth);
rightFace.lineTo(x + width, y + yOffset + height);
rightFace.closePath();
g2d.fill(rightFace);
// Draw bottom face of button (bottom edge)
Color bottomColor = darken(color, 0.5);
g2d.setColor(bottomColor);
Path2D bottomFace = new Path2D.Double();
bottomFace.moveTo(x, y + yOffset + height);
bottomFace.lineTo(x + width, y + yOffset + height);
bottomFace.lineTo(x + width + actualDepth, y + yOffset + height + actualDepth);
bottomFace.lineTo(x + actualDepth, y + yOffset + height + actualDepth);
bottomFace.closePath();
g2d.fill(bottomFace);
// Draw black outlines around button faces
g2d.setColor(Color.BLACK);
g2d.setStroke(new BasicStroke(1.0f));
g2d.draw(topFace);
g2d.draw(rightFace);
g2d.draw(bottomFace);
// Draw the button's text (number or symbol)
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("SansSerif", Font.BOLD, 20));
FontMetrics fm = g2d.getFontMetrics();
int textWidth = fm.stringWidth(label);
int textHeight = fm.getHeight();
g2d.drawString(label,
x + (width - textWidth) / 2,
y + yOffset + (height + textHeight / 2) / 2);
// Restore original drawing settings
g2d.setTransform(originalTransform);
}
// Handle mouse click at specific coordinates
private void handleMousePress(int mouseX, int mouseY) {
// Check all buttons to see if click was inside any of them
for (Map.Entry<String, Rectangle> entry : buttonBounds.entrySet()) {
if (entry.getValue().contains(mouseX, mouseY)) {
String label = entry.getKey();
// Set clicked button for animation effect
clickedButton = label;
repaint();
// Start or restart click animation timer
if (clickTimer.isRunning()) {
clickTimer.restart();
} else {
clickTimer.start();
}
// Handle the button's action
processButtonPress(label);
return;
}
}
}
// Process a button click based on its label
private void processButtonPress(String buttonLabel){
// Clear button (resets calculator)
if (buttonLabel.equals("C")) {
displayText = "0";
startNewInput = true;
operation = null;
firstOperand = 0;
repaint();
return;
}
// Number buttons (0-9)
if ("0123456789".contains(buttonLabel)) {
if (startNewInput) {
// Start a new number
displayText = buttonLabel;
startNewInput = false;
} else if (displayText.length() < MAX_DISPLAY_LENGTH) {
// Add digit to existing number
if (displayText.equals("0")) {
displayText = buttonLabel; // Replace leading zero
} else {
displayText += buttonLabel; // Append digit
}
}
repaint();
return;
}
// Decimal point button
if (buttonLabel.equals(".")) {
if (startNewInput) {
// Start a new decimal number
displayText = "0.";
startNewInput = false;
} else if (!displayText.contains(".") && displayText.length() < MAX_DISPLAY_LENGTH) {
// Add decimal point if not already present
displayText += ".";
}
repaint();
return;
}
// Operation buttons (+, -, *, /)
if ("+-*/".contains(buttonLabel)) {
// Save current number and operation for later
firstOperand = Double.parseDouble(displayText);
operation = buttonLabel;
startNewInput = true;
repaint();
return;
}
// Equals button (performs calculation)
if (buttonLabel.equals("=") && operation != null) {
// Get second number for calculation
double secondOperand = Double.parseDouble(displayText);
double result = 0;
// Perform calculation based on operation
switch (operation) {
case "+":
result = firstOperand + secondOperand;
break;
case "-":
result = firstOperand - secondOperand;
break;
case "*":
result = firstOperand * secondOperand;
break;
case "/":
if (secondOperand != 0) {
result = firstOperand / secondOperand;
} else {
// Prevent division by zero
displayText = "Error";
startNewInput = true;
operation = null;
repaint();
return;
}
break;
}
// Format the result for display
if (result == (long) result) {
// Show whole number without decimal
displayText = String.valueOf((long) result);
} else {
// Show decimal number
displayText = String.valueOf(result);
// Truncate if too long
if (displayText.length() > MAX_DISPLAY_LENGTH) {
try {
// Round to reasonable precision
displayText = String.valueOf(Math.round(result * 1e10) / 1e10);
} catch (Exception e) {
displayText = "Error";
}
}
}
// Reset for next calculation
startNewInput = true;
operation = null;
repaint();
}
}
// Helper method to make a color darker
private Color darken(Color color, double factor) {
return new Color(
Math.max((int)(color.getRed() * factor), 0),
Math.max((int)(color.getGreen() * factor), 0),
Math.max((int)(color.getBlue() * factor), 0)
);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// Create window for calculator
JFrame frame = new JFrame("Calculator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Calculator3D());
frame.pack();
frame.setLocationRelativeTo(null); // Center on screen
frame.setVisible(true); // Show the calculator
}
}
The Final Result:
Download Projects Source Code



