1st's Studio.

Java大作业

字数统计: 3.1k阅读时长: 14 min
2022/05/24

从个人财政系统出发探寻JAVA开源类


1.基础准备

1.1 个人财政系统设计要求

做作业的第一步当然是明确作业的设计要求,然后再开始操作

根据学校里老师提供的文档,JAVA个人理财系统课程设计要求如下:

  • 可以查看所有的收支明细
  • 可以按实践的范围来检索账目,即根据输入实践范围即可显示详细的收支明细。也可以根据收支类型(收入/支出)来检索账目,即显示所有的收入或支出明细
  • 可以增加收入或支出
  • 可以修改或删除某条收支记录,在修改或删除时先要求确认,在用户确认后再进行操作
  • 增加程序监控功能,当结余的账目为负数时,警告已经超支

以及几项具体的要求:

  • 1.登录系统需要用户名和密码,默认用户密码保存在pwd.txt文件或数据库中,验证身份符合方可进入系统。

  • 2.进入系统后,在主界面的“收支明细信息”中列出所有的收支情况,根据查询条件,可在“收支明细信息”中筛选出符合条件的信息,并且在上方更新统计信息

  • 3.在“系统管理”菜单中,可以修改用户的密码(要求新密码保存到pwd.txt文件或数据库中),退出系统。

  • 4.在“收支编辑”菜单中,有以下几种情况:
    • a.如需要录入收支信息,只需将左半边中的信息填写完毕后,点击“录入”按钮,即可将该收支信息存入文件或数据库。注意录入的编号不允许和已有的比编号重复,否则提示出错并清空编号栏。
    • b.点击“查询”按钮,在右边的“显示收支信息”表中将看到最新的全部的收支信息。
    • c.如需修改收支信息,点击右边的“显示收支信息”表中某条收支信息,系统自动将该条信息填写在左边的“编辑收支信息”内,“编号”栏设置为不可编辑状态。用户进行修改(除了编号,其他均允许修改),修改完成后点击“修改”按钮,将修改后数据保存到文件或数据库。
    • d.如需删除收支信息,点击右边的“显示收支信息”表中某条收支信息系统自动将该条信息填写在左边的“编辑收支信息”内,“编号”栏设置为不可编辑状态。用户点击“删除”按钮,对该条数据进行删除,并将左边“编辑收支信息”各输入框清空。
    • e.点击“清空”按钮,将左边的“编辑收支信息”各输入框清空,所有控件均可编辑。

1.2 一些界面基础知识

在明确了课程设计要求之后,可以对需要用的到的基础组件先进行初步的探寻,例如界面容器。

1
2
3
4
5
6
7
8
9
public calss Main{
public static void main(String[] args){
JFrame frame =new JFrame();
frame.setTitle("个人理财系统");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000,1000);
frame.setVisible(true);
}
}

从上述代码可以看出,窗口见面容器时是使用JFrame类来创建的,让我们来看看JFrame、类是如何定义的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class JFrame extend Frame implements WindowConstants,Accessible,RootPaneContainer,TransferHandler.HasGetTransferHandler
{
public JFrame() throws HeadlessException{
super();
frameInit();
}
protected void frameInit(){
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK);
setLocale(JComponent.getDefaultLocale());
setRootPane(createRootPane());
setBackground(UIManager.getColor("control"));
setBackground(UIManager.getColor("control"));
setRootPaneCheckingEnabled(true);
if (JFrame.isDefaultLookAndFeelDecorated()) {
boolean supportsWindowDecorations =
UIManager.getLookAndFeel().getSupportsWindowDecorations();
if (supportsWindowDecorations) {
setUndecorated(true);
getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
}
}
sun.awt.SunToolkit.checkAndSetPolicy(this);
}
}

由于JFrame类的内容较多,这里只展示了JFrame类中的无参构造方法以及构造方法中用到的frameInit方法。可以看到JFrame类继承了Frame类,并且实现了多个接口。

1.3 事件监听器

在我们接下来要做的布局管理器中,事件监听器是必不可少的一个内容,我们需要通过在按钮上添加事件监听器来实现页面间的跳转,以开始界面到登录界面的界面跳转为例来揭示事件监听器的处理过程,话不多说,先上代码:

1
2
3
4
5
6
7
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
login a = new login();
a.setVisible(true);
dis();
}
});

可以看到为一个组件添加事件的具体过程如下:

  • 1.为组件添加事件监听器,其中jb为JButton组件,利用jb.addActionListener()方法监听器
  • 2.当点击按钮时,触发方法监听器内部的事件ActionEvent e,执行函数public void actionPeformed的函数
  • 3.通过actionPerfomed中的语句实现跳转——创建login对象a,设置a可见,利用dis()窗口消去原来的窗口

2.开始设计

2.1 设计开始界面

开始界面为app进入时的界面,理想的布局为上方一张背景图片,下方两个按钮,本别是登录和注册按钮,最后设计出来的效果如下:

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class maincon extends JFrame {
private JButton jb = new JButton("登录");
private JButton zc = new JButton("注册");

public maincon() {
JPanel buttonline = new JPanel();
buttonline.setLayout(new GridLayout(1, 2));
buttonline.add(jb);
buttonline.add(zc);
JLabel jl = new JLabel();
ImageIcon ic = new ImageIcon("界面.png");
jl.setIcon(ic);
JPanel mc = new JPanel();
mc.setLayout(new BorderLayout());
mc.add(jl, BorderLayout.NORTH);
mc.add(buttonline, BorderLayout.SOUTH);
this.add(mc);
this.setSize(700, 550);
this.setResizable(false);
this.setTitle("欢迎来到个人财政系统!");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}

可以从布局的角度来解析这张页面: * 首先先创建两个子布局JPannel,上下分布,上子布局放带有ImageIcon的JLabel,下子布局为并排的两个按钮 * 将两个子布局加入总布局mc,设置其布局方式为BorderLayout,再将两个子布局加入总布局mc.add(jl,BorderLayout.NORTH) mc.add(butthonline,BorderLayout.SOUTH) * 最后将总布局加入窗口

2.2 设计登录、注册、修改密码界面

登录界面是较为初始的一个界面,可以将登录界面写进packge中的login.java中。可以将登录界面划分为三个子JPanel组件,最后再将布局设置为Borderlayout布局进行操作。登录操作涉及到了文件的读操作——即登录时先对账号进行核查,检测account.txt中是否存在该账号,若存在,则在password.txt中查找对应下标的密码是否正确。若均正确,则弹出消息提示框“登录成功”并且进入主操作界面;若是账号或者密码错误,则弹出账号名或密码错误界面并重新输入。现展示核心代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("响应成功");
String acc=nameField.getText();
String pas= String.valueOf(passwordField.getPassword());
System.out.println(acc);
System.out.println(pas);

ArrayList<String> ac = new ArrayList<>();
ArrayList<String> ps = new ArrayList<>();
ReadFile m = new ReadFile();
ac = m.ReadByLine("account.txt");
ps = m.ReadByLine("password.txt");
System.out.println(ac.get(0).equals(acc));
boolean flag = RoN(acc, pas, ac, ps);
if (flag)
JOptionPane.showMessageDialog(null, "登录成功");

else
JOptionPane.showMessageDialog(null, "账号名或密码不正确");
}
});

其中ReadFile类为自己编写的写文件类,大致功能为读取文件中的内容并且将其存进ArrayList中。

修改密码,注册账号的界面以及代码逻辑大体与登录界面原理相同,这里就不再赘述。值得一提的是修改密码的修改文件内容操作,修改文件的内容可以通过多种方法实现,包括但不仅限于记录行号以及删除文件重写操作。

这里采用的是删除文件重写操作,即将文件内容读入ArrayList中,修改ArrayList的对象,再删除文件,重写ArrayList进同名文件。具体代码实现如下(仅展示ActionListener匿名类中的内容)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String acc = yonghuming.getText();
String jm = String.valueOf(jiumm.getPassword());
String xm = String.valueOf(xinmm.getPassword());
String qm = String.valueOf(querenxmm.getPassword());
ArrayList<String> ac = new ArrayList<>();
ArrayList<String> ps = new ArrayList<>();
ReadFile m = new ReadFile();
ac = m.ReadByLine("account.txt");
ps = m.ReadByLine("password.txt");
boolean flag = false;
int index = 0;
for (int i = 0; i < ac.size(); i++)
if (ac.get(i).equals(acc)) {
flag = true;
index = i;
}
if (!flag) {
JOptionPane.showMessageDialog(null, "不存在此用户名!");
return;
}
if (!ps.get(index).equals(jm)) {
JOptionPane.showMessageDialog(null, "旧密码不正确!");
return;
}
if (!xm.equals(qm)) {
JOptionPane.showMessageDialog(null, "两次输入密码不一致!");
return;
}
if (xm.equals("")) {
JOptionPane.showMessageDialog(null, "密码不能为空!");
return;
}
ps.set(index, xm);
System.out.println(ps.get(index));
WriteFile r = new WriteFile();
File file = new File("password.txt");
file.delete();
File file1 = new File("password.txt");
try {
file1.createNewFile();
} catch (IOException ex) {
ex.printStackTrace();
}
for (int i = 0; i < ps.size(); i++)
r.WriteByLine("password.txt", ps.get(i));
JOptionPane.showMessageDialog(null, "密码修改成功,请重新登录!");
maincon mc = new maincon();
t.dispose();
}

2.3 主界面设计

主界面的设计运用的也是面板与布局的交替运用,以及文件的读写操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
public class shouzhicaozuo extends JFrame{
public JMenuBar menuBar=new JMenuBar();
public JMenu menu=new JMenu("返回主界面");
public JPanel zuo=new JPanel();
public JPanel zhong=new JPanel();
public JPanel you=new JPanel();
public JLabel z1=new JLabel("编号:");
public JLabel z2=new JLabel("日期:");
public JLabel z3=new JLabel("类型:");
public JLabel z4=new JLabel("内容:");
public JLabel z5=new JLabel("金额:");
public JButton lr=new JButton("录入");
public JButton xg=new JButton("修改");
public JButton sc=new JButton("删除");
public JButton cx=new JButton("查询");
public JButton qk=new JButton("清空");
public JTextField bh=new JTextField();
public JTextField rq=new JTextField();
public String[] jgg={"收入","支出"};
public JComboBox lx=new JComboBox(jgg);
public String[] jg1={"购物","工作","生活"};
public JComboBox nr=new JComboBox(jg1);
public JTextField je=new JTextField();
String[] columnNames = { "编号", "日期","类型","内容","金额" };
String[][] tb=new String[200][5];
JTable JT=new JTable(tb,columnNames);
public int pp=0;
public shouzhicaozuo(String acc){
this.setTitle("收支操作界面");
this.setLayout(null);
this.setJMenuBar(menuBar);
//将菜单添加到菜单栏上
menuBar.add(menu);
this.setSize(800,500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
setup(acc);
}

public void setup(String account){
menu.addMenuListener(new MenuListener() {
@Override
public void menuSelected(MenuEvent e) {zjm a=new zjm(account);dispose();}
@Override
public void menuDeselected(MenuEvent e) {}
@Override
public void menuCanceled(MenuEvent e) {}
});
ReadFile r=new ReadFile();
ArrayList<String> s = new ArrayList<String>();
s=r.ReadByLine("user\\" + account + ".txt");
for(int i = 0; i< s.size(); i++) {
String[] stra = s.get(i).split(" ");
for(int j=0;j<5;j++){
tb[i][j]=stra[j];
}
}
JT.repaint();
pp=s.size();

zuo.setBorder(BorderFactory.createTitledBorder("编辑收支信息"));
zuo.setLayout(new GridLayout(5,2));
zuo.setBounds(10,10,200,420);
zuo.add(z1);zuo.add(bh);
zuo.add(z2);zuo.add(rq);
zuo.add(z3);zuo.add(lx);
zuo.add(z4);zuo.add(nr);
zuo.add(z5);zuo.add(je);

zhong.setLayout(new GridLayout(5,1));
zhong.setBounds(220,10,100,420);
zhong.add(lr);zhong.add(xg);zhong.add(sc);zhong.add(cx);zhong.add(qk);

you.setBorder(BorderFactory.createTitledBorder("显示收支信息"));
you.setBounds(330,10,450,420);
you.setLayout(new GridLayout(1,1));
JT.setEnabled(false);
JScrollPane scroll = new JScrollPane(JT);
scroll.setSize(300, 200);
you.add(new JScrollPane(JT));
this.add(zuo);
this.add(zhong);
this.add(you);
String k="user\\"+account+".txt";
WriteFile wf=new WriteFile();
lr.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(rq.getText().equals("")||je.getText().equals("")){
JOptionPane.showMessageDialog(null, "信息不完整!");
return;
}
wf.WriteByLine(k,Integer.toString(pp +1)+" "+rq.getText()+" "+lx.getSelectedItem()+" "+nr.getSelectedItem()+" "+je.getText());
ArrayList<String> p=new ArrayList<>();
p=r.ReadByLine("user\\"+account+".txt");
String[] stra1 = p.get(pp).split(" ");
for(int j=0;j<5;j++)
tb[pp][j]=stra1[j];
JT.repaint();
JT.updateUI();
pp += 1;
}
});

xg.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int bt=Integer.parseInt(bh.getText());
if (!(bt<= pp)) {
JOptionPane.showMessageDialog(null, "不存在此编号信息!");
return;
}
if(rq.getText()==null||je.getText()==null) {
JOptionPane.showMessageDialog(null, "信息填写不完整!");
return;
}

ArrayList<String> p=new ArrayList<>();
p=r.ReadByLine("user\\"+account+".txt");
String aa=bh.getText()+" "+rq.getText()+" "+lx.getSelectedItem()+" "+nr.getSelectedItem()+" "+je.getText();
p.set(bt-1,aa);
File file = new File("user\\"+account+".txt");
file.delete();
File file1 = new File("user\\"+account+".txt");
try {
file1.createNewFile();
} catch (IOException ex) {
ex.printStackTrace();
}
for (int i = 0; i < p.size(); i++)
wf.WriteByLine("user\\"+account+".txt", p.get(i));
String[] stra1 = p.get(bt-1).split(" ");
for(int j=0;j<5;j++)
tb[bt-1][j]=stra1[j];
JT.repaint();
JT.updateUI();
JOptionPane.showMessageDialog(null, "记录修改成功!");

}
});
}

}

效果如下:

CATALOG
  1. 1. 从个人财政系统出发探寻JAVA开源类
    1. 1.1. 1.基础准备
      1. 1.1.1. 1.1 个人财政系统设计要求
      2. 1.1.2. 1.2 一些界面基础知识
      3. 1.1.3. 1.3 事件监听器
    2. 1.2. 2.开始设计
      1. 1.2.1. 2.1 设计开始界面
      2. 1.2.2. 2.2 设计登录、注册、修改密码界面
      3. 1.2.3. 2.3 主界面设计