为了练手,抽空做了这款“简易计算器”。就此谈谈在制作过程中遇到的问题。
在制作时,swing组件的布局可累坏我了,还是比较熟悉以前那种“所见即所得”的可视化组件布局方式,下面是UI类,用于绘制UI。
代码如下package me.jerrys.calc;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class CalcUI extends JFrame implements ActionListener {
private CalcAction action;
public HashMap
public HashMap
public JLabel rusultLabel;
public CalcUI(CalcAction action) {
super("简易计算器 - Coded by JerryLocke");
this.action = action;
createUI();
showMessage("程序 Java 简易计算器n作者 @JerryLocken博客 http://111CN.NETn提示 您可以使用键盘进行操作");
}
public void createUI() {
rusultLabel = new JLabel("0");
rusultLabel.setFont(new Font("Arial", 0, 32));
JPanel topPanel = new JPanel();
topPanel.add(rusultLabel);
topPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
JPanel numberPanel = new JPanel(new GridLayout(4, 3, 5, 5));
String[][] numberTitle = { { "7" }, { "8" }, { "9" }, { "4" }, { "5" }, { "6" }, { "1" }, { "2" }, { "3" }, { "0" }, { ".", "小数点" }, { "+/-", "正/负" } };
batchCreateButton(numberTitle, numberPanel, this);
JPanel calc1Panel = new JPanel(new GridLayout(2, 2, 5, 5));
String[][] calc1Title = { { "←", "退格" }, { "C", "清零" }, { "×", "乘" }, { "÷", "除" } };
batchCreateButton(calc1Title, calc1Panel, this);
JPanel calc2Panel = new JPanel(new GridLayout(2, 1, 5, 5));
String[][] calc2Title = { { "-", "减" }, { "=", "等于" } };
batchCreateButton(calc2Title, calc2Panel, this);
topPanel.setBounds(5, 0, 330, 50);
numberPanel.setBounds(5, 50, 200, 313);
calc1Panel.setBounds(210, 51, 130, 153);
calc2Panel.setBounds(277, 209, 62, 153);
JButton calcButton = createButton("+", this);
calcButton.setBounds(210, 209, 62, 153);
calcButton.setFont(new Font("Arial", 0, 20));
this.setLayout(null);
this.add(topPanel);
this.add(numberPanel);
this.add(calc1Panel);
this.add(calc2Panel);
this.add(calcButton);
this.setSize(350, 400);
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventPostProcessor(new KeyEventPostProcessor() {
public boolean postProcessKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_RELEASED) {
String key = "-1";
switch (e.getKeyCode()) {
case KeyEvent.VK_NUMPAD0:
key = "0";
break;
case KeyEvent.VK_NUMPAD1:
key = "1";
break;
case KeyEvent.VK_NUMPAD2:
key = "2";
break;
case KeyEvent.VK_NUMPAD3:
key = "3";
break;
case KeyEvent.VK_NUMPAD4:
key = "4";
break;
case KeyEvent.VK_NUMPAD5:
key = "5";
break;
case KeyEvent.VK_NUMPAD6:
key = "6";
break;
case KeyEvent.VK_NUMPAD7:
key = "7";
break;
case KeyEvent.VK_NUMPAD8:
key = "8";
break;
case KeyEvent.VK_NUMPAD9:
key = "9";
break;
case KeyEvent.VK_MULTIPLY:
key = "×";
break;
case KeyEvent.VK_DIVIDE:
key = "÷";
break;
case 107:
key = "+";
break;
case 109:
if (action.getCurrentText().equals("0")) key = "-";
else key = "-";
break;
case KeyEvent.VK_ENTER:
key = "=";
break;
case 110:
key = ".";
break;
case KeyEvent.VK_BACK_SPACE:
key = "←";
break;
}
if (key.equals("-1")) return true;
buttonMap.get(key).doClick();
}
return true;
}
});
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void batchCreateButton(String[][] buttonTitle, JPanel panel, ActionListener listener) {
for (String[] title : buttonTitle) {
if (title.length == 2) panel.add(createButton(title[0], title[1], this));
else panel.add(createButton(title[0], this));
}
}
public JButton createButton(String title, String tipText, ActionListener listener) {
JButton button = createButton(title, this);
button.setToolTipText(tipText);
return button;
}
public JButton createButton(String title, ActionListener listener) {
JButton button = new JButton(title);
actionsMap.put(button.hashCode(), title);
buttonMap.put(title, button);
button.addActionListener(listener);
button.setFont(new Font("Arial", 0, 20));
return button;
}
public void showMessage(String message) {
JOptionPane.showMessageDialog(null, message);
}
@Override
public void actionPerformed(ActionEvent e) {
String command = (String) actionsMap.get(e.getSource().hashCode());
action.doAction(command);
}
}
刚开始用的是想用边界布局(BorderLayout)+网格布局(GridLayout)制作界面,但是遇到了诸如南北高度宽度难控制,中间填充等问题,最后还是给跪了,直接上了绝对布局。以后在这方面需要多练习。
需要注意的是,为控件增加监听器时,还需要用HashMap来标识每个控件以及存放控件指向的命令。除此之外,上面还使用了 KeyboardFocusManager 为窗口添加快捷键。
以下是动作类,负责处理控件事件以及计算操作等。
package me.jerrys.calc;
import java.math.BigDecimal;
public class CalcAction {
private CalcUI UI;
private BigDecimal lastNum = new BigDecimal("0");
private BigDecimal currentNum = new BigDecimal("0");
private String currentText;
private boolean typeClean = false;
private boolean hadCalced = false;
private MODE currentMode = MODE.PLUS;
private enum MODE {
PLUS, MINUS, MULTIPLY, DIVIDE
}
public static void main(String[] args) {
new CalcAction();
}
public CalcAction() {
this.UI = new CalcUI(this);
}
public void doAction(String command) {
currentText = UI.rusultLabel.getText();
switch (command) {
case "C":
clear();
break;
case "←":
backSpace();
break;
case "+":
setMode(MODE.PLUS);
break;
case "-":
setMode(MODE.MINUS);
break;
case "×":
setMode(MODE.MULTIPLY);
break;
case "÷":
setMode(MODE.DIVIDE);
break;
case "=":
calc();
break;
case "+/-":
addSign();
break;
default:
addNumber(command);
}
}
private void calc() {
if (hadCalced && typeClean) return;
currentNum = new BigDecimal(currentText);
try {
switch (currentMode) {
case PLUS:
lastNum = lastNum.add(currentNum);
break;
case MINUS:
lastNum = lastNum.subtract(currentNum);
break;
case MULTIPLY:
lastNum = lastNum.multiply(currentNum);
break;
case DIVIDE:
lastNum = lastNum.divide(currentNum, 16,
BigDecimal.ROUND_HALF_DOWN);
break;
}
} catch (Exception e) {
UI.showMessage("发生错误:" + e.getMessage());
return;
}
String resultText = lastNum.toString();
if (resultText.indexOf(".") > 0) { // 消除小数多余位数
resultText = resultText.replaceAll("0+?$", "");
resultText = resultText.replaceAll("[.]$", "");
}
setResultText(resultText);
typeClean = true;
hadCalced = false;
}
private void setMode(MODE mode) {
if (!hadCalced && !typeClean) {
calc();
currentMode = mode;
return;
}
lastNum = new BigDecimal(currentText);
currentMode = mode;
typeClean = true;
hadCalced = true;
}
private void addSign() {
if (currentText.equals("0") || currentText.equals("")) return;
if (currentText.startsWith("-")) setResultText(currentText.substring(1));
else setResultText("-" + currentText);
}
private void backSpace() {
if (currentText.equals("0") || currentText.equals("")) return;
if (currentText.length() == 1) {
setResultText("0");
return;
}
setResultText(currentText.substring(0, currentText.length() - 1));
}
private void addNumber(String num) {
String resultText = currentText;
if (typeClean == true) {
resultText = "0";
typeClean = false;
}
if (num.equals(".") && currentText.lastIndexOf(".") != -1) return;
if ((resultText.equals("0") || resultText.equals(""))
&& !num.equals("."))
resultText = "";
resultText = resultText + num;
setResultText(resultText);
}
private void clear() {
currentNum = new BigDecimal("0");
lastNum = new BigDecimal("0");
typeClean = false;
currentMode = MODE.PLUS;
setResultText("0");
}
public String getCurrentText() {
return currentText;
}
private void setResultText(String text) {
UI.rusultLabel.setText(text);
}
}
在这里也遇到了问题,刚开始用的是 double 类型存放数值,进行加减乘除计算会有精度问题,会导致意想不到的结果,比如10-9.88会得到 0.11999999999999922 。为了解决这个可以,JDK提供了 BigDecimal 一包用于精准计算,使用方法见上。
(时间紧,未完善,勿喷)
javascript学习指南|Java 简易计算器之学习笔记
http://m.bbyears.com/wangyezhizuo/51626.html
推荐访问:java学习路线