Skip to content

Instantly share code, notes, and snippets.

@shiracamus
Last active September 25, 2021 20:19
Show Gist options
  • Save shiracamus/79cfaf88e9fddcc0d0dd115862410362 to your computer and use it in GitHub Desktop.
Save shiracamus/79cfaf88e9fddcc0d0dd115862410362 to your computer and use it in GitHub Desktop.
//package myProgram;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import javax.swing.JComponent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class Calculator extends JFrame {
public static void main(String[] args) {
Calculator calculator = new Calculator("my電卓");
calculator.setBounds(100, 100, 400, 250);
calculator.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
calculator.setVisible(true);
}
// 数字入力や計算結果はentryに代入
BigDecimal entry = BigDecimal.ZERO;
// "1+2=" 等の二項演算は operand=1 operator="+" entry=2 にして calculate()
BigDecimal operand = BigDecimal.ZERO;
final BinaryOperator NOP = () -> {};
BinaryOperator operator = NOP;
String point = ""; // 浮動小数点入力なら"."、数値入力
boolean enteringNumber = false; // "1+2√34" を "1+34" にするため
boolean replaceableOperator = false; // "1+-/*2" を "1*2" にするため
final DecimalFormat DISPLAY_FORMAT = new DecimalFormat("0.#########");
JTextField display = new JTextField("0", 16);
NumberButton bt0 = new NumberButton("0");
NumberButton bt1 = new NumberButton("1");
NumberButton bt2 = new NumberButton("2");
NumberButton bt3 = new NumberButton("3");
NumberButton bt4 = new NumberButton("4");
NumberButton bt5 = new NumberButton("5");
NumberButton bt6 = new NumberButton("6");
NumberButton bt7 = new NumberButton("7");
NumberButton bt8 = new NumberButton("8");
NumberButton bt9 = new NumberButton("9");
BinaryButton btAdd = new BinaryButton("+", () -> {
setEntry(operand.add(entry));
});
BinaryButton btMultply = new BinaryButton("×", () -> {
setEntry(operand.multiply(entry));
});
BinaryButton btSubtract = new BinaryButton("-", () -> {
setEntry(operand.subtract(entry));
});
BinaryButton btDivide = new BinaryButton("÷", () -> {
if (entry.equals(BigDecimal.ZERO)) {
setEntry(BigDecimal.ZERO); //0除算時
} else {
setEntry(operand.divide(entry, 9, RoundingMode.HALF_EVEN));
}
});
UnaryButton btPoint = new UnaryButton(".", () -> {
if (!enteringNumber) {
setEntry(BigDecimal.ZERO);
enteringNumber = true;
}
point = ".";
});
UnaryButton btClear = new UnaryButton("C", () -> {
operand = BigDecimal.ZERO;
operator = NOP;
setEntry(BigDecimal.ZERO);
});
UnaryButton btNegative = new UnaryButton("+/-", () -> {
setEntry(entry.multiply(new BigDecimal("-1")));
});
UnaryButton btSqrt = new UnaryButton("√", () -> {
try {
setEntry(entry.sqrt(new MathContext(9)));
} catch (ArithmeticException e) {
setEntry(BigDecimal.ZERO); // 負数時
}
});
UnaryButton btEqual = new UnaryButton("=", () -> {
calculate();
});
Calculator(String title) {
super(title);
buildComponents();
}
void buildComponents() {
getContentPane().add(buildDisplay(), BorderLayout.NORTH);
getContentPane().add(buildButtons(), BorderLayout.CENTER);
}
JComponent buildDisplay() {
JPanel p = new JPanel();
display.setHorizontalAlignment(JTextField.RIGHT);
display.setEditable(false);
p.add(display);
return p;
}
JComponent buildButtons() {
JPanel p = new JPanel();
p.add(buildNumbers(), BorderLayout.CENTER);
p.add(buildFunctions(), BorderLayout.EAST);
return p;
}
JComponent buildNumbers() {
JPanel p = new JPanel();
p.setLayout(new GridLayout(5, 3));
p.add(btClear); p.add(btNegative); p.add(btSqrt);
p.add(bt7); p.add(bt8); p.add(bt9);
p.add(bt4); p.add(bt5); p.add(bt6);
p.add(bt1); p.add(bt2); p.add(bt3);
p.add(bt0); p.add(btPoint);
return p;
}
JComponent buildFunctions() {
JPanel p = new JPanel();
p.setLayout(new GridLayout(5, 1));
p.add(btDivide);
p.add(btMultply);
p.add(btSubtract);
p.add(btAdd);
p.add(btEqual);
return p;
}
void setEntry(BigDecimal value) {
entry = value;
display.setText(DISPLAY_FORMAT.format(entry));
enteringNumber = false;
replaceableOperator = false;
}
void calculate() {
operator.calculate();
operator = NOP;
enteringNumber = false;
replaceableOperator = false;
}
interface UnaryOperator {
void operate();
}
interface BinaryOperator {
void calculate();
}
class NumberButton extends JButton {
public NumberButton(final String number) {
super(number);
addActionListener((ActionEvent event) -> {
if (!enteringNumber) {
setEntry(BigDecimal.ZERO);
}
try {
setEntry(new BigDecimal(entry + point + number));
} catch (NumberFormatException e) {
// 小数点が複数回入力された場合例外発生、無視する
}
point = "";
enteringNumber = true;
replaceableOperator = false;
});
}
}
class UnaryButton extends JButton {
UnaryButton(String label, final UnaryOperator unary) {
super(label);
addActionListener((ActionEvent event) -> {
unary.operate();
});
}
}
class BinaryButton extends JButton {
BinaryButton(String label, final BinaryOperator binary) {
super(label);
addActionListener((ActionEvent event) -> {
if (replaceableOperator) {
operator = binary;
return;
}
calculate();
operand = entry;
operator = binary;
enteringNumber = false;
replaceableOperator = true;
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment