面向对象程序设计
面向对象程序设计:
1 背诵记录文件的读写
关键代码如下:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Vector;
class RRecordGetter {
// 将传入的Vector写入filePath(背诵记录文件)文件中
public static boolean saveRRecords(
String filePath, Vector<ReciteRecord> vect) {
try {
ObjectOutputStream outputStream =
new ObjectOutputStream(
new FileOutputStream(filePath));
// 遍历vect,并写入记录文件
for (ReciteRecord i : vect) {
outputStream.writeUTF(i.word);
outputStream.writeLong(i.startDate);
outputStream.writeLong(i.lastDate);
outputStream.writeInt(i.stage);
outputStream.writeInt(i.strange);
}
outputStream.close();
} catch (IOException e) {
System.out.println(e.getMessage());
return false;
}
return true;
}
// 读取记录文件,返回Vector
public static Vector<ReciteRecord> loadRRecords(
String filePath, int n) {
Vector<ReciteRecord> vect = new Vector<ReciteRecord>();
try {
ObjectInputStream inputStream =
new ObjectInputStream(
new FileInputStream(filePath));
for (int i = 0; i < n; ++i) {
ReciteRecord temp = new ReciteRecord();
temp.word = inputStream.readUTF();
temp.startDate = inputStream.readLong();
temp.lastDate = inputStream.readLong();
temp.stage = inputStream.readInt();
temp.strange = inputStream.readInt();
vect.addElement(temp);
}
inputStream.close();
} catch(Exception e) {
System.out.println(e.getMessage());
}
return vect;
}
}
2 词库文件的读取
// WordManager.java
package whypro.memorize;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;
public class WordManager {
protected String filePath;
protected String fileName;
protected int index;
protected int indexBound;
protected String word;
protected String phonetic;
protected String interp;
protected String thesName;
public WordManager(String filePath, String fileName) throws IOException {
this.filePath = filePath;
this.fileName = fileName;
calcIndexBound();
}
public void getWordAndInterp() throws IOException {
Random random = new Random(System.currentTimeMillis());
this.index = Math.abs(random.nextInt() % indexBound);
FileReader fr = new FileReader(filePath + '/' + fileName);
BufferedReader br = new BufferedReader(fr);
String line = br.readLine(); // 词库名称
thesName = line;
for (int i = 0; i < 4 * index; i++) {
line = br.readLine();
}
while (!line.equals("")) {
line = br.readLine();
}
this.word = br.readLine();
this.phonetic = br.readLine();
this.interp = br.readLine();
br.close();
fr.close();
}
public void calcIndexBound() throws IOException {
FileReader fr = new FileReader(filePath + '/' + fileName);
BufferedReader br = new BufferedReader(fr);
String line = br.readLine(); // 词库名称
int indexBound = 0;
while (line != null) {
if (line.equals("")) {
indexBound++;
}
line = br.readLine();
}
this.indexBound = indexBound;
br.close();
fr.close();
}
}
3 统计已背诵的单词:
// ReciteStat.java
package whypro.memorize;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
class ReciteStat extends JFrame {
final JTable table;
Vector<ReciteRecord> recordsVector;
public ReciteStat() {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
// 从记录文件中读取单词背诵记录并存入Object[][] o中
recordsVector = RRecordGetter.loadRRecords("./record/recite.rec", 100);
Object[][] o = new Object[recordsVector.size()][5];
int j = 0;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = null;
for (ReciteRecord i : recordsVector) {
o [j][0] = i.word;
str = format.format(new Date(i.startDate));
o [j][1] = str;
str = format.format(new Date(i.lastDate));
o [j][2] = str;
o [j][3] = i.stage;
o [j][4] = i.strange;
++j;
}
String[] names = {"单词", "首次记忆时间", "上次记忆时间", "记忆阶段", "陌生度"};
table = new JTable(o, names);
mainPanel.add(new JScrollPane(table));
this.add(mainPanel);
//
this.setTitle("背诵情况统计");
this.setSize(600, 400);
this.setResizable(false);
// 使窗口居中
Toolkit kit = Toolkit.getDefaultToolkit(); // 定义工具包
Dimension screenSize = kit.getScreenSize(); // 获取屏幕的尺寸
int screenWidth = screenSize.width / 2; // 获取屏幕的宽
int screenHeight = screenSize.height / 2; // 获取屏幕的高
int height = this.getHeight();
int width = this.getWidth();
// 使窗口居中
setLocation(screenWidth - width / 2, screenHeight - height / 2);
this.setVisible(true);
}
}
4 访问自定义字体文件
由于软件需要显示音标,因此定义了MyFont类,用于使用自定义字体显示单词的音标。关键代码如下:
// MyFont.java
package whypro.memorize;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class MyFont {
public static Font getFont(String filePath, String fileName, int style, float size)
throws FontFormatException, IOException {
File file = new File(filePath + '/' + fileName);
FileInputStream fi;
BufferedInputStream fb;
Font font = null;
fi = new FileInputStream(file);
fb = new BufferedInputStream(fi);
// 创建自定义字体
font = Font.createFont(Font.TRUETYPE_FONT, fb);
font = font.deriveFont(style, size);
return font;
}
}
5. GridBagLayout布局方式
软件使用了Swing更强大的GridBagLayout布局方式,代码如下:
// WordTester.java
package whypro.memorize;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Vector;
import javax.swing.*;
class WordTester extends JFrame implements KeyListener, ActionListener {
private static final long serialVersionUID = 1L;
WordManager randomWord;
final private JPanel mainPanel;
final private JLabel lblEnglish;
final private JLabel lblPhonetic;
final private JTextArea txtChinese;
final private JLabel lblStatus;
final private JMenuBar menuBar = new JMenuBar();
final private JMenu fileMenu = new JMenu("文件 (F)");
final private JMenuItem chooseThItem = new JMenuItem("选择词库 (T)");
final private JMenuItem statItem = new JMenuItem("词汇统计 (S)");
final private JMenuItem exitItem = new JMenuItem("退出 (X)");
final private JMenu helpMenu = new JMenu("帮助 (H)");
final private JMenuItem aboutItem = new JMenuItem("关于 (A)");
String strEnglish; // 单词
String strPhonetic; // 音标
String strChinese; // 释义
String strTName; // 词库名
String strSpelling = "";
int wordLength; // 单词长度
int strange = 0; // 陌生度
// 标志位,忽略一次Type事件
boolean isCorrect = false;
String fontPath = "./font"; // 字体路径
String fontName = "TOPhonetic.ttf";
String thesPath = "./thesaurus/TOFEL.txt"; // 词库路径
String thesName = "";
String recordPath = "./record/recite.rec"; // 背诵记录文件路径
Vector<ReciteRecord> recordsVector = new Vector<ReciteRecord>(); // 背诵记录
public WordTester() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
// 初始化菜单栏
fileMenu.setMnemonic('F');
menuBar.add(fileMenu);
chooseThItem.setMnemonic('T');
fileMenu.add(chooseThItem);
chooseThItem.setMnemonic('T');
fileMenu.add(statItem);
exitItem.setMnemonic('S');
fileMenu.add(exitItem);
helpMenu.setMnemonic('H');
menuBar.add(helpMenu);
aboutItem.setMnemonic('A');
helpMenu.add(aboutItem);
chooseThItem.addActionListener(this);
statItem.addActionListener(this);
exitItem.addActionListener(this);
aboutItem.addActionListener(this);
this.setJMenuBar(menuBar);
lblEnglish = new JLabel(strEnglish);
lblEnglish.setBackground(Color.WHITE);
// lblEnglish.setFont(new Font("Bradley Hand ITC", Font.BOLD, 50));
lblEnglish.setFont(new Font("Arial", Font.BOLD, 50));
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
c.weightx = 1;
mainPanel.add(lblEnglish, c);
lblPhonetic = new JLabel(strPhonetic);
lblPhonetic.setBackground(Color.WHITE);
// 获取音标字体
try {
lblPhonetic.setFont(MyFont.getFont(
fontPath, fontName, Font.PLAIN, 20));
} catch (FontFormatException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
System.exit(0);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
System.exit(0);
}
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 2;
c.weightx = 1;
c.weighty = 0.1;
mainPanel.add(lblPhonetic, c);
txtChinese = new JTextArea(strChinese);
txtChinese.setLineWrap(true);
txtChinese.setFont(new Font("华文仿宋", Font.PLAIN, 28));
//txtChinese.setBackground(Color.black);
//txtChinese.setForeground(Color.white);
txtChinese.setEditable(false);
c.fill = GridBagConstraints.BOTH;
c.gridx = 0;
c.gridy = 3;
c.weightx = 1;
c.weighty = 2;
mainPanel.add(txtChinese, c);
lblStatus = new JLabel(strTName);
// lblEnglish.setFont(new Font("Bradley Hand ITC", Font.BOLD, 50));
lblStatus.setFont(new Font("宋体", Font.PLAIN, 12));
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 4;
c.weighty = 0.2;
mainPanel.add(lblStatus, c);
txtChinese.setFocusable(false);
this.addKeyListener(this);
lblEnglish.addKeyListener(this);
lblPhonetic.addKeyListener(this);
txtChinese.addKeyListener(this);
// 软件运行时将背诵记录从文件载入内存
recordsVector = RRecordGetter.loadRRecords(recordPath, 100);
newRandomWord();
this.add(mainPanel);
//
this.setTitle("whyNotMemorize");
this.setSize(400, 400);
this.setResizable(false);
// 使窗口居中
Toolkit kit = Toolkit.getDefaultToolkit(); // 定义工具包
Dimension screenSize = kit.getScreenSize(); // 获取屏幕的尺寸
int screenWidth = screenSize.width / 2; // 获取屏幕的宽
int screenHeight = screenSize.height / 2; // 获取屏幕的高
int height = this.getHeight();
int width = this.getWidth();
setLocation(screenWidth - width / 2, screenHeight - height / 2);
this.setVisible(true);
}
@Override
public void keyPressed(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {}
@Override
public void keyTyped(KeyEvent e) {
// 当拼写正确时,忽略一次键盘事件,并产生新词
if (isCorrect) {
isCorrect = false;
newRandomWord();
return;
}
char ch = e.getKeyChar();
// 单词长度限制
if (strSpelling.length() < strEnglish.length()) {
// 字母限制
if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z' || ch == '-'
|| ch == '(' || ch == ')') {
lblEnglish.setForeground(Color.BLACK);
strSpelling += ch;
lblEnglish.setText(strSpelling);
}
}
// 退格键
if (strSpelling.length() > 0) {
if (ch == '\b') {
strSpelling = strSpelling
.substring(0, strSpelling.length() - 1);
if (strSpelling.length() > 0) {
lblEnglish.setText(strSpelling);
} else {
lblEnglish.setText(" ");
}
}
}
// 回车键
if (ch == '\n' || ch == ' ') {
if (strSpelling.equals(strEnglish)) {
// 当拼写正确时,以蓝色字体显示,并设置isCorrect标志
strSpelling = "";
lblEnglish.setForeground(Color.blue);
lblEnglish.setText(strEnglish);
isCorrect = true;
// 生成该单词背诵数据,并写入文件
ReciteRecord record = new ReciteRecord(
strEnglish,
System.currentTimeMillis(), System.currentTimeMillis(),
0, strange);
recordsVector.addElement(record);
RRecordGetter.saveRRecords(recordPath, recordsVector);
} else {
// 当拼写不正确时,以红色字体显示
strSpelling = "";
lblEnglish.setForeground(Color.red);
lblEnglish.setText(strEnglish);
// 陌生度
strange++;
}
}
// Tab键
if (ch == '`') {
newRandomWord();
}
}
public void newRandomWord() {
strSpelling = "";
strange = 0;
// Random random = new Random(System.currentTimeMillis());
// int index = Math.abs(random.nextInt() % 3000);
try {
randomWord = new WordManager(thesPath, thesName);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
System.exit(0);
}
getTestWord();
}
public void setEventToLable(String strWord) {
lblEnglish.setText(strWord);
}
// 从词库文件中随机抽取一个单词
public void getTestWord() {
try {
randomWord.getWordAndInterp();
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
System.exit(0);
}
strEnglish = randomWord.word;
strPhonetic = randomWord.phonetic;
strChinese = randomWord.interp;
strTName = randomWord.thesName;
wordLength = strEnglish.length();
lblEnglish.setText(" ");
lblPhonetic.setText(strPhonetic);
txtChinese.setText(strChinese);
lblStatus.setText(strTName);
}
public void chooseThesaurus() {
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("./thesaurus"));
chooser.setDialogTitle("选择词库");
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
thesPath = chooser.getSelectedFile().getPath();
// thesName = chooser.getSelectedFile().getName();
newRandomWord();
} else {
return;
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == chooseThItem) {
chooseThesaurus();
}
else if (e.getSource() == statItem) {
new ReciteStat();
}
else if (e.getSource() == exitItem){
System.exit(0);
}
else if (e.getSource() == aboutItem) {
JOptionPane.showMessageDialog(this,"欢迎大家\n ");
}
}
}