小组开发,感谢组内大佬带我飞,我就是个做ppt的混子
说明:
①代码仅供参考,实现了课本上的所有功能并且通过了上台展示。
②编写用的eclipse,具体的文件路径结构已经不记得了。
③下面的代码是很多个Java程序放在一起了,想要用把代码顺一遍,找找文件的开始结尾位置。
④ 注释是个好东西,建议学弟学妹不要直接白嫖,尽量读一读代码。
package ExerciseTest;
public class AdditionOperation extends BinaryOperation{
AdditionOperation(){
generateBinaryOperation('+');
}
public boolean checkingCalculation(int anInteger){
//方法重写,使该类的算式符合规定的加法算式标准
if(anInteger<=upper)
return true;
else
return false;
}
int calculate(int left,int right){
return left + right;
}
}
class SubstractOperation extends BinaryOperation{
SubstractOperation(){
generateBinaryOperation('-');
}
public boolean checkingCalculation(int anInteger){
//方法重写,使该类的算式符合规定的减法算式标准
if(anInteger>=lower)
return true;
else
return false;
}
int calculate(int left,int right){
return left - right;
}
}
package ExerciseTest;
import java.io.Serializable;
import java.util.Random;
public abstract class BinaryOperation implements Serializable{
static final int upper = 100;
static final int lower = 0;
private int left_operand = 0,right_operand = 0;
private char operator = '+';
private int value = 0;
public void insert(String left, String right){
//新增:insert通过调用这个方法可以直接插入算式
left_operand = Integer.valueOf(left);
right_operand = Integer.valueOf(right);
value = calculate(left_operand, right_operand);
}
public void insert(int left, int right){
//新增:int参数的insert
left_operand = left;
right_operand = right;
value = calculate(left_operand, right_operand);
}
//重载public String toString
public String toString(){
String s;
String Charop = String.valueOf(operator);
s = left_operand+Charop+right_operand+"=";
return s;
}
// getXX 返回需要访问的数字和符号
public char getOperator(){
return operator;
}
public int getleft_operand(){
return left_operand;
}
public int getright_operand(){
return right_operand;
}
public int getvalue() {
return value;
}
protected void generateBinaryOperation(char anOperator){
//传入的anOperator即为该类生成的算式的运算符号
int left,right,result;
Random random = new Random();
left = random.nextInt(upper+1);
do{
//约束,两位整数必须符合约束条件才能赋值给成员函数
right = random.nextInt(upper+1);
result = calculate(left,right);
}while(!(checkingCalculation(result)));
left_operand = left;
right_operand = right;
operator = anOperator;
value = result;
}
abstract boolean checkingCalculation(int anInteger);
//检查是否符合算式标准
abstract int calculate(int left, int right);
//计算算式结果
public boolean equals(BinaryOperation anOperation){
//方法将该对象的数字符号与另一个对象的数字符号做比较,起到检查是否重复的作用
return operator==anOperation.getOperator()&&
right_operand==anOperation.getright_operand()&&
left_operand==anOperation.getleft_operand();
}
}
package ExerciseTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Exercise implements Serializable{
private static final long serialVersionUID = 6829563053067592708L;
private int OperationCount = 0;//新增:记录这个Exercise的算式总数
protected String FileName ;//新增:练习名称
public String Addr = "D:/加减法练习/";//新增:练习地址
private int current = 0;//记录当前访问位置
class Answers implements Serializable { //答案内部类
private static final long serialVersionUID = -232662116583465565L;
String content; //答案内容
boolean correct; //正确性
public Answers() {content = ""; correct = false;}
public Answers(String ans, boolean cr) {
content = ans; correct = cr;
}
}
private ArrayList operationList = new ArrayList();
private List answers = new ArrayList<>(); //用户填写的所有题目的答案列表
private ExerciseType currentType; //当前题目类型,为串行化保存用
public ExerciseType getCurrentType() {return currentType;}
public String getExerciseType() {
String s = new String();
switch(currentType) {
case ADDandSUB:
s = "加减混合";
break;
case ADD:
s = "仅加法";
break;
case SUB:
s = "仅减法";
break;
}
return s;
}
private void setCurrentType(ExerciseType type) { this.currentType = type;}
public void setAnswer(int index, String ans) {
//设置答案内容并判断正确性
BinaryOperation op;
op = operationList.get(index); //获取算式
String result = String.valueOf(op.getvalue()); //获取正确结果
String tans = ans.trim();//获取用户输入的答案
answers.set(index, new Answers(tans, result.equals(tans)));
//设置答案内容和正确性,index位置上设置为对应的answer对象,对象里面保存用户答案和是否正确
}
public String getAnswer(int index) { //获取答案
return answers.get(index).content;
}
public void clearAnswers() { //清空答案(全设为空,错误)
for (int i = 0; i < answers.size(); i++)
answers.set(i, new Answers("", false));
}
public int Correct() { //统计正确题数
int correctAmount = 0;
for (int i = 0; i < answers.size(); i++) {
if (getJudgement(i))
correctAmount++;
}
return correctAmount;
}
public boolean getJudgement(int index) {
//获取判题结果
return answers.get(index).correct;
}
public void saveObject(String filename, Exercise exercise) throws ExerciseIOException{
//串行化存储对象
FileOutputStream f = null;
try {
f = new FileOutputStream(filename);
//可以传入一个字符串的文件地址,地址不为空时,自动为字符串创建File对象
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
ObjectOutputStream s = null;
try {
s = new ObjectOutputStream(f);
//定义ObjectOutputStream对象需要用一个FileOutputStream来构造文件字节输出流对象
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
try {
s.writeObject(exercise);//向文件中输出算式
s.flush();
//刷新此输出流并强制写出所有缓冲的输出字节。
//flush 的常规协定是:如果此输出流的实现已经缓冲了以前写入的任何字节,则调用此方法指示应将这些字节立即写入它们预期的目标。
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
try {
s.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
public static Exercise loadObject(String filename) throws ExerciseIOException{
//串行化载入对象
FileInputStream in = null;
try {
in = new FileInputStream(filename);
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
ObjectInputStream s = null;
try {
s = new ObjectInputStream(in);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
Exercise exercise = null;
try {
exercise = (Exercise) s.readObject();
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
try {
s.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return exercise;
}
public void generateWithFormerType(int operationCount) {
//采用原题型生成新题目
switch(currentType) {
case ADDandSUB:
this.generateBinaryExercise(operationCount);
break;
case ADD:
this.generateAdditionExercise(operationCount);
break;
case SUB:
this.generateBinaryExercise(operationCount);
break;
}
}
public enum ExerciseType {
ADD , SUB, ADDandSUB,
}
//重构结束
//创建一个关于BinaryOperation(算式)的动态数组
public Exercise() {
File aFile = new File(Addr);
if(!aFile.exists())
aFile.mkdir();
}
public boolean hasNext(){
return current<=operationList.size()-1;
}//若数组还有元素,则返回是,否则返回否
public BinaryOperation next(){
return operationList.get(current++);
}//若有元素,返回当前元素,当前访问位置移动到下一个位置
public boolean contains(BinaryOperation anOperation){
boolean flag = true;
int size = operationList.size();
if(size==0){//如果数组里没有算式,返回false,允许加入数组
return false;
}
for(int i = 0;i0){
do{
anOperation = generateOperation();
}while(contains(anOperation));
operationList.add(anOperation);
answers.add(new Answers());
//将anOperation 加入到Exercise中
operationCount--;
}
}
public void generateAdditionExercise(int operationCount){
//随机生成加法算式并加入数组
setCurrentType(ExerciseType.ADD ); //设置题目类型
answers.clear();
operationList.clear();
current = 0;
OperationCount = operationCount;
FileName= "Addition_exercise_"+operationCount+"_";
BinaryOperation anOperation1;
while(operationCount>0){
do{anOperation1 = new AdditionOperation();}while(contains(anOperation1));
operationList.add(anOperation1);//将anOperation 加入到Exercise中
answers.add(new Answers());
operationCount--;
}
}
public void generateSubstractExercise(int operationCount){
//随机生成减法算式并加入数组
setCurrentType(ExerciseType.SUB );
operationList.clear();
answers.clear();
operationList.clear();
current = 0;
OperationCount = operationCount;
FileName= "Substract_exercise_"+operationCount+"_";
BinaryOperation anOperation1;
while(operationCount>0){
do{anOperation1 = new SubstractOperation();}while(contains(anOperation1));
operationList.add(anOperation1);
answers.add(new Answers());
//将anOperation 加入到Exercise中
operationCount--;
}
}
public void writeCSVExercise()//生成文件
{
int count = OperationCount;//算式数量
FileName = Addr + FileName+".csv";//生成习题文件名称
String PracticeName = FileName.replaceAll("exercise", "practice");
System.out.println(FileName);
System.out.println(PracticeName);
try {
File file =new File(FileName);
if(!file.exists()){
file.createNewFile();
}
File pfile = new File(PracticeName);
if(!pfile.exists()) {
pfile.createNewFile();
}
FileWriter fileWritter = new FileWriter(file,false);
for(int i=0;i opResults=new ArrayList ();
FileInputStream in = new FileInputStream(anExerciseFile);
int b = 0;
String eqString="";
while(b!=-1){
b = in.read();
if((char)b==','||(char)b=='\r'){
opResults.add(Integer.valueOf(eqString));
eqString="";
}else if((char)b!='\r'&&(char)b!='\n')
eqString+=(char)b;
}
in.close();
Integer[] bb=new Integer[opResults.size()];
return opResults.toArray(bb);
}
private Integer[] getAnswers(Exercise exercise)throws Exception{
//获得正确答案
ArrayListopAnswer = new ArrayList();
while(exercise.hasNext()) {
//System.out.println(exercise.next());
opAnswer.add(exercise.next().getvalue());
}
Integer[]bb = new Integer[opAnswer.size()];
return opAnswer.toArray(bb);
}
public void writeCSVReport(File aReportFile) throws IOException{
//传入一个文件,将批改结果输出到该文件中
OperationCount = correct+wrong;//算式数量
String str;
str = "答案:"+ CheckingName;
FileWriter FW = new FileWriter(aReportFile,false);
FW.write(str+",\r\n");
str = "答案总数:"+OperationCount;
FW.write(str+",\r\n");
str = "正确:"+correct;
FW.write(str+",\r\n");
str = "错误:"+wrong;
FW.write(str+",\r\n");
str = "得分:"+score;
FW.write(str+",\r\n");
System.out.println("批改文件已生成");
FW.close();
}
public void Practice(Exercise anExercise) throws Exception {
//传入一个习题对象,并查找目录下的练习文件,然后进行批改,生成文件
getAllName(anExercise.FileName);
Integer[]Results = getResults(anExercise);
Integer[]Answers = getAnswers(anExercise);
evaluate(Answers,Results);
String Addr_Name = anExercise.Addr+CheckingName;
File file = new File(Addr_Name);
if(!file.exists())
file.createNewFile();
writeCSVReport(file);
}
public void getAllName(String Name){
//分解习题文件名称,便于找到练习文件名称和生成批改文件名称
String type,count;
int a,b,c;
a = Name.indexOf("_");
b = Name.indexOf("_",a+1);
c = Name.indexOf("_",b+1);
type = Name.substring(0,a);
count = Name.substring(b+1,c);
CheckingName = type+"_checking_"+count+"_.csv";
PracticeName = type+"_practice_"+count+"_.csv";
}
}
package ExerciseTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
public class OperationBase{//算式基类
static final int UPPER = 100;
private BinaryOperation[][]AdditionBase;//加法算式基
private BinaryOperation[][]SubstractBase;//减法算式基
public void displayBase(BinaryOperation[][] base) {
//测试方法,显示传进来的算式基的所有算式
for(BinaryOperation[]ba:base) {
for(BinaryOperation aa:ba) {
if(aa!=null)
System.out.print(aa.toString()+'\t');
}
System.out.println();
}
}
public Exercise generationExercise(int count, BinaryOperation[][] Base) {
//传入算式基,该算式基可以是加法算式基也可以是减法算式基,根据这个算式基随机生成算式并返回习题对象
Exercise anExercise = new Exercise();
BinaryOperation anOperation;
Random random = new Random();
int i, j;
while(count>0) {
do {
i = random.nextInt(UPPER+1);
j = random.nextInt(UPPER+1);
anOperation = Base[i][j];
}while(anOperation==null||anExercise.contains(anOperation));
anExercise.Add(anOperation);
count--;
}
return anExercise;
}
public Exercise generationExercise(int count,BinaryOperation[][]AddBase,BinaryOperation[][]SubBase) {
//传入两个算式基,既加法和减法算式基,根据这两个算式基随机生成混合算式并返回习题对象
Exercise anExercise = new Exercise();
BinaryOperation anOperation;
Random random = new Random();
int i, j, ran;
while(count>0) {
ran = random.nextInt(2);
switch(ran) {
case 0:
do {
i = random.nextInt(UPPER+1);
j = random.nextInt(UPPER+1);
anOperation = AddBase[i][j];
}while(anOperation==null||anExercise.contains(anOperation));
anExercise.Add(anOperation);
count--;
break;
case 1:
do {
i = random.nextInt(UPPER+1);
j = random.nextInt(UPPER+1);
anOperation = SubBase[i][j];
}while(anOperation==null||anExercise.contains(anOperation));
anExercise.Add(anOperation);
count--;
break;
}
}
return anExercise;
}
//以下三个方法被直接调用,返回一个习题,并生成文件
public Exercise generateAdditionExercise(int count) {
//生成加法习题
Exercise exercise;
exercise = generationExercise(count,AdditionBase);
exercise.FileName = "Addition_exercise_"+count+"_";
return exercise;
}
public Exercise generateSubstractExercise(int count) {
//生成减法习题
Exercise exercise;
exercise = generationExercise(count,SubstractBase);
exercise.FileName = "Substract_exercise_"+count+"_";
return exercise;
}
public Exercise generateBinaryExercise(int count) {
//生成加法习题
Exercise exercise;
exercise = generationExercise(count,AdditionBase,SubstractBase);
exercise.FileName = "MixOperation_exercise_"+count+"_";
return exercise;
}
public OperationBase() throws Throwable {
//构造函数,算式基对象实例化就判断算式基文件是否存在,若存在则直接读入,若不存在就生成
File aFile = new File("d:/加减法练习/AdditionOperationBase.csv");
File bFile = new File("d:/加减法练习/SubstractOperationBase.csv");
if(aFile.exists()&&bFile.exists()) {
readOperationBase(aFile, bFile);
System.out.println("已从文件读入算式基");
}
else {
writeOperationBase();
System.out.println("已将算式基写入文件");
}
}
public void readOperationBase(File aFile,File bFile) throws IOException {
//读入算式基
FileInputStream fisa = new FileInputStream(aFile);
FileInputStream fisb = new FileInputStream(bFile);
AdditionBase = new BinaryOperation[UPPER+1][UPPER+1];
SubstractBase = new BinaryOperation[UPPER+1][UPPER+1];
BinaryOperation op;
String eqString = "";
int b ;
for(int i = 0;i<=UPPER;i++) {
for(int j = 0;j<=UPPER-i;j++) {
while(true) {
b = fisa.read();
if(b=='\r'||b=='\n')
continue;
if(b==',')
break;
else
eqString+=(char)b;
}
op = Exercise.AddSubOperation(eqString);
AdditionBase[i][j] = op;
eqString = "";
}
}
for(int i = 0;i<=UPPER;i++) {
for(int j = 0;j<=i;j++) {
while(true) {
b = fisb.read();
if(b=='\r'||b=='\n')
continue;
if(b==',')
break;
else
eqString+=(char)b;
}
op = Exercise.AddSubOperation(eqString);
SubstractBase[i][j] = op;
eqString = "";
}
}
fisa.close();
fisb.close();
}
public void writeOperationBase() throws Throwable {
//生成算式基文件
AdditionBase = new BinaryOperation[UPPER+1][UPPER+1];
SubstractBase = new BinaryOperation[UPPER+1][UPPER+1];
BinaryOperation op;
File aFile = new File("d:/加减法练习/AdditionOperationBase.csv");
File bFile = new File("d:/加减法练习/SubstractOperationBase.csv");
if(!aFile.exists())
aFile.createNewFile();
FileWriter FW = new FileWriter(aFile,false);
for(int i = 0;i<=UPPER;i++){
for(int j = 0;j<=UPPER-i;j++) {
op = new AdditionOperation();
op.insert(i, j);
AdditionBase[i][j] = op;
FW.write(op.toString());
FW.write(",");
}
FW.write("\r\n");
}
FW.close();
op = new SubstractOperation();
if(!bFile.exists())
bFile.createNewFile();
FW = new FileWriter(bFile,false);
for(int i = 0;i<=UPPER;i++){
for(int j = 0;j<=i;j++) {
op = new SubstractOperation();
op.insert(i, j);
SubstractBase[i][j] = op;
FW.write(op.toString());
FW.write(",");
}
FW.write("\r\n");
}
FW.close();
displayBase(AdditionBase);
displayBase(SubstractBase);
}
}
package GUITest;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.GroupLayout.Alignment;
import javax.swing.border.EmptyBorder;
import ExerciseTest.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class PracticeGui extends JFrame {
private static final long serialVersionUID = 6478286329988994564L;
private JPanel contentPane;
/**
* Launch the application.
*/
static final int WINDOW_WIDTH = 600;
static final int WINDOW_HEIGHT = 500;
static final int OP_AMOUNT = 20;
static final int OP_COLUMN = 5;
static final int OP_WIDTH = 65;
static final int ANSWER_WIDTH = 35;
static final int COMPONET_HEIGHT = 25;
static final int STAT_WIDTH = 200;
static final int STAT_HEIGHT = 100;
private JTextField [] tfOp;
private JTextField [] tfAns;
private JTextArea taStat;
private Exercise exercises;
private int correctAmount;
private int wrongAmount;
private double accuracy;
private double errorrate;
private JButton btnNewButton;
private JButton btnNewButton_1;
private void judge() {
BinaryOperation op;
correctAmount = wrongAmount = 0;
accuracy = errorrate = 0;
for (int i = 0; i < OP_AMOUNT; i++) {
op = exercises.getOperation(i);
String result = String.valueOf(op.getvalue());
String answer = tfAns[i].getText().trim();
if (result.contentEquals(answer)) {
tfAns[i].setBackground(Color.GREEN);
correctAmount++;
}
else {
tfAns[i].setBackground(Color.RED);
wrongAmount++;
}
}
accuracy = (correctAmount * 1.0 / OP_AMOUNT * 1.0) * 100.0;
errorrate = (wrongAmount * 1.0 / OP_AMOUNT * 1.0) * 100.0;
String ac = String.format("%.2f", accuracy);
ac += '%';
String er = String.format("%.2f", errorrate);
er += '%';
taStat.setText("统计信息:\n\n" + "总题数: " + OP_AMOUNT
+ " 正确题数 :" + correctAmount + " 错误题数: " + wrongAmount + '\n'
+ " 正确率: " + ac + " 错误率: " + er);
}
private void initExerciseComponets() {
exercises = new Exercise();
exercises.generateAdditionExercise(OP_AMOUNT);
tfOp = new JTextField[OP_AMOUNT];
tfAns = new JTextField[OP_AMOUNT];
for (int i = 0; i < OP_AMOUNT; i++) {
tfOp[i] = new JTextField();
tfOp[i].setBounds(20 + (i % OP_COLUMN) * (OP_WIDTH + ANSWER_WIDTH + 5),
20 + (i / OP_COLUMN) * (COMPONET_HEIGHT + 10),
OP_WIDTH,
COMPONET_HEIGHT);
tfOp[i].setHorizontalAlignment(JTextField.RIGHT);
tfOp[i].setEditable(false);
contentPane.add(tfOp[i]);
tfAns[i] = new JTextField();
tfAns[i].setBounds(20 + (i % OP_COLUMN) * (OP_WIDTH + ANSWER_WIDTH + 5) + OP_WIDTH,
20 + (i / OP_COLUMN) * (COMPONET_HEIGHT + 10),
ANSWER_WIDTH,
COMPONET_HEIGHT);
tfAns[i].setEditable(true);
contentPane.add(tfAns[i]);
}
//按钮与统计信息文本域
JButton button = new JButton("\u91CD\u65B0\u751F\u6210\u9898\u76EE");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
exercises.generateAdditionExercise(OP_AMOUNT);
updateExerciseComponets();
}
});
JButton button_1 = new JButton("\u63D0\u4EA4\u7B54\u6848");
button_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
judge();
}
});
taStat = new JTextArea();
btnNewButton = new JButton("New button");
contentPane.add(btnNewButton, BorderLayout.WEST);
btnNewButton_1 = new JButton("New button");
contentPane.add(btnNewButton_1, BorderLayout.EAST);
GroupLayout gl_contentPane = new GroupLayout(contentPane);
gl_contentPane.setHorizontalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGap(46)
.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING, false)
.addComponent(button_1, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(button, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(47)
.addComponent(taStat, GroupLayout.PREFERRED_SIZE, 330, GroupLayout.PREFERRED_SIZE)
.addContainerGap(246, Short.MAX_VALUE))
);
gl_contentPane.setVerticalGroup(
gl_contentPane.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_contentPane.createSequentialGroup()
.addContainerGap(290, Short.MAX_VALUE)
.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING)
.addComponent(taStat, GroupLayout.PREFERRED_SIZE, 97, GroupLayout.PREFERRED_SIZE)
.addGroup(gl_contentPane.createSequentialGroup()
.addComponent(button)
.addGap(36)
.addComponent(button_1)))
.addGap(64))
);
contentPane.setLayout(gl_contentPane);
}
private void updateExerciseComponets() {
BinaryOperation op;
for (int i = 0; i < OP_AMOUNT; i++) {
op = exercises.getOperation(i);
tfOp[i].setText(op.toString());
tfAns[i].setBackground(Color.WHITE);
tfAns[i].setText(" ");
}
String ac = String.format("%.2f", accuracy);
ac += '%';
String er = String.format("%.2f", errorrate);
er += '%';
taStat.setText("统计信息:\n\n" + "总题数: " + OP_AMOUNT
+ " 正确题数 :" + correctAmount + " 错误题数: " + wrongAmount + '\n'
+ " 正确率: " + ac + " 错误率: " + er);
taStat.setEditable(false);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
PracticeGui frame = new PracticeGui();
frame.setTitle("100以内的口算练习程序");
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public PracticeGui() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, WINDOW_WIDTH, WINDOW_HEIGHT);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
initExerciseComponets();
updateExerciseComponets();
}
}
package GUITest;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import ExerciseTest.BinaryOperation;
import ExerciseTest.Exercise;
import ExerciseTest.ExerciseIOException;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JMenuBar;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JToolBar;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JTextField;
import java.awt.event.ActionListener;
import java.io.File;
import java.awt.event.ActionEvent;
import javax.swing.JLabel;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
public class PracticeGui2 extends JFrame {
private static final long serialVersionUID = -8069047189470765958L;
private JPanel contentPane;
private boolean submitted;//确定当前位置的题目是不是已经写了
static final int WINDOW_WIDTH = 600;
static final int WINDOW_HEIGHT = 500;
static final int OP_AMOUNT = 20;
static final int OP_COLUMN = 5;
static final int OP_WIDTH = 65;
static final int ANSWER_WIDTH = 35;
static final int COMPONET_HEIGHT = 25;
static final int STAT_WIDTH = 200;
static final int STAT_HEIGHT = 100;
//设置窗口大小和相关变量的位置
private JTextField [] tfOp;//放算式的文本域
private JTextField [] tfAns;//放答案的框
private Exercise exercise;
private int totalAmount;
private int correctAmount;
private int wrongAmount;
private double accuracy;
private double errorrate;
private int currentPage;
private int totalPages;
JToolBar toolBar = new JToolBar(); //导入
JToolBar toolBar_1 = new JToolBar(); //题目
JToolBar toolBar_2 = new JToolBar(); // 翻页
//三个工具栏,对应三个功能组合
JButton button_7 = new JButton("\u4E0A\u4E00\u9875"); //上一页
JButton button_8 = new JButton("\u4E0B\u4E00\u9875"); //下一页
JMenuItem menuItem_5 = new JMenuItem("\u4E0A\u4E00\u9875"); //菜单上一页
JMenuItem menuItem_6 = new JMenuItem("\u4E0B\u4E00\u9875"); //菜单下一页
JLabel label = new JLabel("");
JLabel lblNewLabel = new JLabel("New label"); //当前页数
JLabel lblNewLabel_1 = new JLabel("New label"); //总页数
JLabel lblNewLabel_3 = new JLabel("New label"); //状态栏
JLabel lblNewLabel_4 = new JLabel("New label"); //答案状态栏
private void reachBegin() {
this.button_7.setEnabled(false);
this.menuItem_5 .setEnabled(false);
//一开始没有上一页,禁止点击上一页
}
private void reachEnd() {
this.button_8.setEnabled(false);
this.menuItem_6 .setEnabled(false);
//到达最后一页后没有下一页,禁止点击下一页
}
private void leaveBegin() {
this.button_7.setEnabled(true);
this.menuItem_5 .setEnabled(true);
}
private void leaveEnd() {
this.button_8.setEnabled(true);
this.menuItem_6 .setEnabled(true);
}
//这两个方法用于离开最后一页或者离开第一页的时候,可以点击第一页或者最后一页,要解开禁止
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
PracticeGui2 frame = new PracticeGui2();//定义窗口对象
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void initComponets() {
//加入一定数目的算式和答案
this.submitted = false;
exercise = new Exercise();
exercise.generateAdditionExercise(OP_AMOUNT);
this.currentPage = 1;
this.totalPages = 1;
this.reachBegin();
this.reachEnd();
tfOp = new JTextField[OP_AMOUNT];
tfAns = new JTextField[OP_AMOUNT];
//生成对应数目的算式位置和答案位置
for (int i = 0; i < OP_AMOUNT; i++) {
//循环加入算式和答案,配对加入
tfOp[i] = new JTextField();
tfOp[i].setBounds(20 + (i % OP_COLUMN) * (OP_WIDTH + ANSWER_WIDTH + 5),
50 + (i / OP_COLUMN) * (COMPONET_HEIGHT + 10),
OP_WIDTH,COMPONET_HEIGHT);
//设置算式框的位置和大小,位置遵循一定的规律
tfOp[i].setHorizontalAlignment(JTextField.RIGHT);
//设置算式框里面的算式为右对齐
tfOp[i].setEditable(false);//算式位置是不可更改的
contentPane.add(tfOp[i]);
tfAns[i] = new JTextField();
tfAns[i].setBounds(20 + (i % OP_COLUMN) * (OP_WIDTH + ANSWER_WIDTH + 5) + OP_WIDTH,
50 + (i / OP_COLUMN) * (COMPONET_HEIGHT + 10),
ANSWER_WIDTH,
COMPONET_HEIGHT);
tfAns[i].setEditable(true);
contentPane.add(tfAns[i]);
//答案框的加入和算式框相同
}
}
private void updateComponets() {
//显示题目和答案框以及其对应格式
this.totalPages = exercise.length() / OP_AMOUNT;
this.lblNewLabel.setText("第 " + String.valueOf(this.currentPage) + " 页");
this.lblNewLabel_1.setText("共 " + String.valueOf(this.totalPages) + " 页");
//设置页数标签
if (this.currentPage == 1)
this.reachBegin();
else
this.leaveBegin();
if (this.currentPage == this.totalPages)
this.reachEnd();
else
this.leaveEnd();
//设置当前页到第一页或者最后一页的时候点击权限
BinaryOperation op;
for (int i = 0; i < OP_AMOUNT; i++) {
op = exercise.getOperation((currentPage - 1) * OP_AMOUNT + i);
tfOp[i].setText(op.toString());
//获得已经生成的算式中的算式并加入到文本域中
if(!submitted) {
tfAns[i].setBackground(Color.WHITE);
//没写东西的时候答案框设置为白色
}
else {
if(exercise.getJudgement((currentPage - 1) * OP_AMOUNT + i))
tfAns[i].setBackground(Color.GREEN);
else
tfAns[i].setBackground(Color.RED);
//已经提交了的话就根据答案是否正确,将答案框设置为不同的颜色
}
tfAns[i].setText(exercise.getAnswer((currentPage - 1) * OP_AMOUNT + i));
}
String s = new String();
if(!submitted ) {
s = "点击【提交】后可获取";
}
else {
//计算正确率等一系列量
totalAmount = exercise.length();
correctAmount = exercise.Correct();
wrongAmount = totalAmount - correctAmount;
accuracy = (correctAmount * 1.0 / totalAmount * 1.0) * 100.0;
errorrate = (wrongAmount * 1.0 / totalAmount * 1.0) * 100.0;
String co = String.format("%d", correctAmount);
String wr = String.format("%d", wrongAmount);
String ac = String.format("%.2f", accuracy);
ac += '%';
String er = String.format("%.2f", errorrate);
er += '%';
s = "正确题数 : " + co + " " + "错误题数 : " + wr + " " +
"正确率 : " + ac + " " + "错误率 : " + er;
}
lblNewLabel_3.setText("状态: "
+ "题目类型 - " + exercise.getExerciseType()
+ " "
+ "题目数量 - " + exercise.length());
lblNewLabel_4.setText(s);
}
private void impExercise() {
//导入题目
JFileChooser jfc = new JFileChooser();//新建一个文件选择器
jfc.showOpenDialog(null);//设置参数的值可以改变文件选择器在屏幕上的弹出位置
File file = jfc.getSelectedFile();
try {
exercise = Exercise.loadObject(file.getAbsolutePath());
JOptionPane.showMessageDialog(null, "导入题目成功!"
,"提示",JOptionPane.INFORMATION_MESSAGE);
this.submitted = false;
updateComponets();
}catch(NullPointerException npe) {
}catch(ExerciseIOException e) {
JOptionPane.showMessageDialog(null, "导入题目失败,可能是因为选择了错误的文件",
"错误",JOptionPane.ERROR_MESSAGE);
}
}
private void expExercise() {
//导出题目
JFileChooser jfc = new JFileChooser();
jfc.showOpenDialog(null);
File file = jfc.getSelectedFile();
try {
exercise.saveObject(file.getAbsolutePath(), exercise);
//把这一道题目导出到文件里面
JOptionPane.showMessageDialog(null, "导出题目成功!"
,"提示",JOptionPane.INFORMATION_MESSAGE);
}catch(NullPointerException npe) {
}catch(ExerciseIOException e) {
JOptionPane.showMessageDialog(null, "导出题目失败,可能是因为选择了错误的文件",
"错误",JOptionPane.ERROR_MESSAGE);
}
}
//导入导出题目用的都是JFileChooser对象,用这个对象来获得目标路径,之后用file对象进行导入导出
private void prePage() { //上翻一页
getAnswers(this.currentPage);
//上下翻页的时候,先把当前页的内容存下来
if(this.currentPage == this.totalPages)
this.leaveEnd();
if(--currentPage == 1)
this.reachBegin();
//调整页数之后对页数上下翻页的限制
this.lblNewLabel.setText(String.valueOf(currentPage));
updateComponets();
}
private void nextPage() { //下翻一页
getAnswers(this.currentPage);
if(this.currentPage == this.totalPages)
this.leaveEnd();
if(++currentPage == totalPages)
this.reachEnd();
this.lblNewLabel.setText(String.valueOf(currentPage));
updateComponets();
}
private void getAnswers(int pageIndex) { //获取答案
for (int i = 0; i < OP_AMOUNT; i++) {
exercise.setAnswer((pageIndex - 1) * OP_AMOUNT + i, tfAns[i].getText());
}
}
private void generateExercise() { //重新生成题目
int length = exercise.length();
exercise.generateWithFormerType(length);
//通过两次调用方法,更新题目对象,实现重新生成题目的功能
updateComponets();
}
private void judgeAnswer() {
this.submitted = true;
getAnswers(this.currentPage);
updateComponets();//把目前做的题目进行批改,更新答案框的颜色
}
private void clearAnswers() {
exercise.clearAnswers();
this.submitted = false;
updateComponets();
//把答案清空,提交状态改为未提交
}
public PracticeGui2() {
//可视化窗口编辑GUI界面,添加对应的动作监听
setTitle("100\u4EE5\u5185\u7684\u53E3\u7B97\u7EC3\u4E60\u7A0B\u5E8F");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 570, 376);
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu menu = new JMenu("\u6587\u4EF6");
menuBar.add(menu);
JMenuItem menuItem = new JMenuItem("\u5BFC\u5165");
menu.add(menuItem);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
impExercise();
}
});
JMenuItem menuItem_1 = new JMenuItem("\u5BFC\u51FA");
menu.add(menuItem_1);
menuItem_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
expExercise();
}
});
JMenu menu_1 = new JMenu("\u9898\u76EE\u8BBE\u7F6E");
menuBar.add(menu_1);
JMenu menuItem_7 = new JMenu("\u6839\u636E\u7C7B\u578B\u751F\u6210");
menu_1.add(menuItem_7);
JCheckBoxMenuItem chckbxmntmadd = new JCheckBoxMenuItem("\u52A0\u6CD5\u9898\u76EE");
menuItem_7.add(chckbxmntmadd);
chckbxmntmadd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int length = exercise.length();
exercise.generateAdditionExercise(length);
updateComponets();
}
});
JCheckBoxMenuItem chckbxmntmsub = new JCheckBoxMenuItem("\u51CF\u6CD5\u9898\u76EE");
menuItem_7.add(chckbxmntmsub);
chckbxmntmsub.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int length = exercise.length();
exercise.generateSubstractExercise(length);
updateComponets();
}
});
JCheckBoxMenuItem chckbxmntmas = new JCheckBoxMenuItem("\u52A0\u51CF\u6DF7\u5408");
menuItem_7.add(chckbxmntmas);
chckbxmntmas.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int length = exercise.length();
exercise.generateBinaryExercise(length);
updateComponets();
}
});
JMenu menuItem_8 = new JMenu("\u6839\u636E\u6570\u91CF\u751F\u6210");
menu_1.add(menuItem_8);
JCheckBoxMenuItem checkBoxMenuItem_3 = new JCheckBoxMenuItem("20");
menuItem_8.add(checkBoxMenuItem_3);
checkBoxMenuItem_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
exercise.generateWithFormerType(20);
updateComponets();
}
});
JCheckBoxMenuItem checkBoxMenuItem_4 = new JCheckBoxMenuItem("40");
menuItem_8.add(checkBoxMenuItem_4);
checkBoxMenuItem_4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
exercise.generateWithFormerType(40);
updateComponets();
}
});
JCheckBoxMenuItem checkBoxMenuItem_5 = new JCheckBoxMenuItem("100");
menuItem_8.add(checkBoxMenuItem_5);
checkBoxMenuItem_5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
exercise.generateWithFormerType(100);
updateComponets();
}
});
JMenu menu_2 = new JMenu("\u9898\u76EE\u64CD\u4F5C");
menuBar.add(menu_2);
JMenuItem menuItem_2 = new JMenuItem("\u91CD\u65B0\u751F\u6210");
menu_2.add(menuItem_2);
menuItem_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
generateExercise();
clearAnswers();
}
});
JMenuItem menuItem_3 = new JMenuItem("\u6E05\u7A7A");
menu_2.add(menuItem_3);
menuItem_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clearAnswers();
}
});
JMenuItem menuItem_4 = new JMenuItem("\u63D0\u4EA4");
menu_2.add(menuItem_4);
menuItem_4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
judgeAnswer();
}
});
JMenu menu_3 = new JMenu("\u67E5\u770B");
menuBar.add(menu_3);
menu_3.add(menuItem_5);
menuItem_5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
prePage();
}
});
menu_3.add(menuItem_6);
menuItem_6.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
nextPage();
}
});
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
JLabel lblNewLabel_2 = new JLabel("New label");
lblNewLabel_2.setText("------------------------------------------"
+ "------------------------------------------"
+ "-----------------------------------------------------");
GroupLayout gl_contentPane = new GroupLayout(contentPane);
gl_contentPane.setHorizontalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addComponent(toolBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(toolBar_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(toolBar_2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addGroup(gl_contentPane.createSequentialGroup()
.addGap(137)
.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGap(63)
.addComponent(lblNewLabel)
.addGap(42)
.addComponent(lblNewLabel_1))
.addComponent(label)))
.addComponent(lblNewLabel_2)
.addGroup(gl_contentPane.createSequentialGroup()
.addContainerGap()
.addComponent(lblNewLabel_3))
.addGroup(gl_contentPane.createSequentialGroup()
.addContainerGap()
.addComponent(lblNewLabel_4)))
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
gl_contentPane.setVerticalGroup(
gl_contentPane.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
.addComponent(toolBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(toolBar_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(toolBar_2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addPreferredGap(ComponentPlacement.RELATED, 169, Short.MAX_VALUE)
.addComponent(label)
.addGap(13)
.addGroup(gl_contentPane.createParallelGroup(Alignment.BASELINE)
.addComponent(lblNewLabel_1)
.addComponent(lblNewLabel))
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(lblNewLabel_2)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(lblNewLabel_3)
.addPreferredGap(ComponentPlacement.UNRELATED)
.addComponent(lblNewLabel_4)
.addGap(19))
);
button_7.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
prePage();
}
});
toolBar_2.add(button_7);
button_8.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
nextPage();
}
});
toolBar_2.add(button_8);
JButton button_4 = new JButton("\u91CD\u65B0\u751F\u6210");
button_4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
generateExercise();
clearAnswers();
}
});
toolBar_1.add(button_4);
JButton button = new JButton("\u6E05\u7A7A");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clearAnswers();
}
});
toolBar_1.add(button);
JButton button_6 = new JButton("\u63D0\u4EA4");
button_6.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
judgeAnswer();
}
});
toolBar_1.add(button_6);
JButton button_2 = new JButton("\u5BFC\u5165");
button_2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
impExercise();
}
});
toolBar.add(button_2);
JButton button_3 = new JButton("\u5BFC\u51FA");
button_3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
expExercise();
}
});
toolBar.add(button_3);
contentPane.setLayout(gl_contentPane);
initComponets();
updateComponets();
}
}