pocketbook

pocketbook

基于Swing和JDBC开发的桌面程序,JavaSE基础的综合.使用git进行版本管理,合作开发

github地址:https://github.com/Cscar2H/pocketbook

数据库和表

1
create database pocketbook

根据需求,设计了3个表

1.配置表信息 config 
    用于保存预算和用于备份还原的路径
2.消费分类表 category
    用于保存消费分类
3.记录表 record
    用于保存每一笔的消费记录,并且会用到消费分类

config表

使用键值对保存了key_和value,例如key=”budget” value=”200”,表示预算是200元

category表

name表示分类的类名

record表

spend 表示单次花费
cid 对应的消费分类表的中记录的id
comment 备注信息
date 日期
分类表和记录表之间的关系是一对多,record表中cid就是外键

功能开发

主界面:


在startup包下新建一个类Bootstrap,这个类专门负责启动程序,作为一个程序的启动入口,可以执行一些初始化操作.

使用了SwingUtilities.invokeAndWait的方式启动图形界面
同时使用了调度线程,保证创建和显示界面的操作都在同一个线程中

1
2
3
4
5
6
7
8
9
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
//是否显示主窗体
MainFrame.instance.setVisible(true);
//在主界面中显示SpendPanel的界面
MainPanel.instance.workingPanel.show(SpendPanel.instance);
}
});

使用监听器

界面效果

创建一个独立的监听器类ToolBarListener,实现接口ActionListener,重写了该接口中的actionPerformed方法。

在工具栏里的每一个按钮都使用一个这样的监听器.

通过ActionEvent.getSource()获取事件是哪个按钮发出来的.根据不同的按钮,发出切换不同的功能面板.

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
public class ToolBarListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
MainPanel p = MainPanel.instance;
JButton b = (JButton) e.getSource();
if (b == p.bReport) {
p.workingPanel.show(ReportPanel.instance);
}
if (b == p.bCategory) {
p.workingPanel.show(CategoryPanel.instance);
}
if (b == p.bSpend) {
p.workingPanel.show(SpendPanel.instance);
}
if (b == p.bRecord) {
p.workingPanel.show(RecordPanel.instance);
}
if (b == p.bConfig) {
p.workingPanel.show(ConfigPanel.instance);
}
if (b == p.bBackup) {
p.workingPanel.show(BackupPanel.instance);
}
if (b == p.bRecover) {
p.workingPanel.show(RecoverPanel.instance);
}

}
}

实例化一个ToolBarListener监听器,给工具栏的按钮添加listener监听器对象.
在MainPanel面板中使用监听器

1
2
3
4
5
6
7
8
9
10
11
12
private void addListener() {
ToolBarListener listener = new ToolBarListener();

bSpend.addActionListener(listener);
bRecord.addActionListener(listener);
bCategory.addActionListener(listener);
bReport.addActionListener(listener);
bConfig.addActionListener(listener);
bBackup.addActionListener(listener);
bRecover.addActionListener(listener);

}

初始化数据库配置

效果

业务类

ConfigService业务类,这个类是监听器直接调用的类,然后再通过ConfigService去调用ConfigDAO。

之前DAO是直接链接数据库,在操作数据库之前,需要对一些数据进行预处理,这些就可以放在业务类里进行.

ConfigService

1.初始化
因为设置信息里有两个数据,一个是预算,一个是Mysql路径。 这两个信息,无论如何都应该是存在数据库中的。 所以会调用init把他们俩初始化。

2.init(String key, String value) 方法
首先根据key去查找,如果不存在,就使用value的值插入一条数据。

3.get(String key) 
根据键获取相应的值

4.update(String key, String value) 
更新键对应的值
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
package me.cscar.service;

import me.cscar.dao.ConfigDAO;
import me.cscar.domain.Config;

public class ConfigService {
public static final String BUDGET = "budget";
public static final String PATH = "mysqlPath";
public static final String DEFAULT_BUDGET = "500";

static ConfigDAO dao= new ConfigDAO();
static{
init();
}

public static void init(){
init(budget, default_budget);
init(mysqlPath, "");
}

private static void init(String key, String value) {

Config config= dao.getByKey(key);
if(config==null){
Config c = new Config();
c.setKey(key);
c.setValue(value);
dao.add(c);
}
}

public String get(String key) {
Config config= dao.getByKey(key);
return config.getValue();
}

public void update(String key, String value){
Config config= dao.getByKey(key);
config.setValue(value);
dao.update(config);
}

public int getIntBudget() {
return Integer.parseInt(get(budget));
}

}

ConfigListener

监听器ConfigListener,这个监听器是用在更新按钮上的

1.判断输入的预算是否为整数

2.判断输入的MySQL

3.如果判断通过,就调用业务类ConfigService更新数据
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
package me.cscar.gui.listener;

import me.cscar.gui.panel.ConfigPanel;
import me.cscar.gui.util.GUIUtil;
import me.cscar.service.ConfigService;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JOptionPane;


public class ConfigListener implements ActionListener{

@Override
public void actionPerformed(ActionEvent e) {
ConfigPanel p = ConfigPanel.instance;
//判断
if(!GUIUtil.checkNumber(p.tfBudget, "预算")) {
return;
}
String mysqlPath =p.tfMysqlPath.getText();
//判断MySQL路径是否正确
if(0!=mysqlPath.length()){
File commandFile = new File(mysqlPath,"bin/mysql");
if(!commandFile.exists()){
JOptionPane.showMessageDialog(p, "Mysql路径不正确");
p.tfMysqlPath.grabFocus();
return;
}
}

ConfigService cs= new ConfigService();
cs.update(ConfigService.budget,p.tfBudget.getText());
cs.update(ConfigService.mysqlPath,mysqlPath);

JOptionPane.showMessageDialog(p, "设置修改成功");

}

}