Java实战之管家婆记账系统(10)——修改账目界面及功能实现

本节概要

本节将实现账目记录的修改。

 

创建界面

建立修改FXML文件,就是在view包下创建alterAccountFrame.fxml文件,使用Scene Builder设计界面组件,各个控件的属性和事件方法参考下面的代码:

<?xml version="1.0" encoding="UTF-8"?>
​
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="AccountSystem.controller.AlterAccountFrameController">
    <children>
        <VBox alignment="CENTER" focusTraversable="true" layoutX="147.0" layoutY="10.0" prefHeight="400.0"
              prefWidth="326.0" spacing="20.0">
            <children>
                <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label text="序号:"/>
                        <TextField fx:id="idTextField" prefWidth="240.0" promptText="请填入记录的序号:"/>
                    </children>
                </HBox>
                <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label text="类型:"/>
                        <HBox alignment="CENTER_LEFT" prefHeight="30.0" prefWidth="240.0" spacing="50.0">
                            <children>
                                <RadioButton fx:id="outputRadioButton" disable="true" mnemonicParsing="false"
                                             onAction="#outputRadioButtonEvent" text="支出">
                                    <toggleGroup>
                                        <ToggleGroup fx:id="group"/>
                                    </toggleGroup>
                                </RadioButton>
                                <RadioButton fx:id="inputRadioButton" disable="true" mnemonicParsing="false"
                                             onAction="#inputRadioButtonEvent" text="收入" toggleGroup="$group"/>
                            </children>
                        </HBox>
                    </children>
                </HBox>
                <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label text="金额:"/>
                        <TextField fx:id="moneyTextField" disable="true" prefHeight="30.0" prefWidth="240.0"/>
                    </children>
                </HBox>
                <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label text="分类:"/>
                        <ComboBox fx:id="classificationComboBox" disable="true" onAction="#classificationComboBoxEvent"
                                  prefHeight="30.0" prefWidth="240.0" promptText="请选择分类:"/>
                    </children>
                </HBox>
                <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label text="备注:"/>
                        <TextArea fx:id="memoTextArea" disable="true" prefHeight="200.0" prefWidth="240.0"
                                  promptText="请填入备注:"/>
                    </children>
                </HBox>
                <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
                    <children>
                        <Label text="日期:"/>
                        <DatePicker fx:id="datePickerText" disable="true" prefHeight="30.0" prefWidth="240.0"/>
                    </children>
                </HBox>
                <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="50.0">
                    <children>
                        <Button fx:id="checkButton" mnemonicParsing="false" onAction="#checkButtonEvent" text="查询"/>
                        <Button fx:id="alterButton" disable="true" mnemonicParsing="false" onAction="#alterButtonEvent"
                                text="更改"/>
                    </children>
                </HBox>
            </children>
            <opaqueInsets>
                <Insets/>
            </opaqueInsets>
            <padding>
                <Insets bottom="20.0"/>
            </padding>
        </VBox>
    </children>
</AnchorPane>

然后是在controller包下创建与之对应的控制器类AlterAccountFrameController.java,从Scene Builder中复制基本控制器类组件对象代码到该类中:

package AccountSystem.controller;
​
import AccountSystem.bean.Classification;
import AccountSystem.bean.Record;
import AccountSystem.bean.Session;
import AccountSystem.dao.ClassificationDao;
import AccountSystem.dao.RecordDao;
import AccountSystem.tools.PublicTools;
import AccountSystem.tools.SimpleTools;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
​
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
​
/**
 * 更改账目界面控制器
 *
 * @author lck100
 */
public class AlterAccountFrameController {
    private PublicTools publicTools = new PublicTools();
​
    @FXML
    private String selectedCoboboxItem = null;
​
    @FXML
    private String selectedRadioButton = null;
​
    @FXML
    private TextField idTextField;
​
    @FXML
    private RadioButton outputRadioButton;
​
    @FXML
    private Button alterButton;
​
    @FXML
    private TextField moneyTextField;
​
    @FXML
    private DatePicker datePickerText;
​
    @FXML
    private RadioButton inputRadioButton;
​
    @FXML
    private TextArea memoTextArea;
​
    @FXML
    private ComboBox<?> classificationComboBox;
​
    /**
     * “支出”单选按钮的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void outputRadioButtonEvent(ActionEvent actionEvent) {
        
    }
​
    /**
     * “收入”单选按钮的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void inputRadioButtonEvent(ActionEvent actionEvent) {
        
    }
​
    /**
     * ”分类“下拉列表框的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void classificationComboBoxEvent(ActionEvent actionEvent) {
        
    }
​
    /**
     * ”查询“按钮的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void checkButtonEvent(ActionEvent actionEvent) {
        
    }
​
    /**
     * ”更改“按钮的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void alterButtonEvent(ActionEvent actionEvent) {
        
    }
}

接着在MainApp.java中创建方法加载FXML文件:

    /**
     * 操作结果:更改账目界面
     */
    public Scene initAlterFrame() {
        try {
​
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(MainApp.class.getResource("view/alterAccountFrame.fxml"));
            AnchorPane page = (AnchorPane) loader.load();
​
            Stage mainFrameStage = new Stage();
            mainFrameStage.setTitle("更改账目");
            mainFrameStage.setResizable(true);
            mainFrameStage.setAlwaysOnTop(false);
            mainFrameStage.initModality(Modality.APPLICATION_MODAL);
            mainFrameStage.initOwner(primaryStage);
            Scene scene = new Scene(page);
            mainFrameStage.setScene(scene);
​
            mainFrameStage.showAndWait();
            return scene;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

最后是在MainPageController.java中给修改菜单项注册事件,即:

    /**
     * ”修改“菜单项的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void alterMenuItemEvent(ActionEvent actionEvent) {
        // 刷新数据
        initialize();
        // 调用修改界面控制器
        mainApp.initAlterFrame();
    }

运行程序,界面如下:

 

 

实现功能

实现修改功能,首先关于界面上的一些如单选按钮、下拉列表框组件的事件方法,参见下面的代码,这些代码在添加功能的章节说过,所以不再说明。

    public void initialize() {
        idTextField.setText("");
        inputRadioButton.setSelected(false);
        inputRadioButton.setDisable(true);
        outputRadioButton.setSelected(false);
        outputRadioButton.setDisable(true);
        moneyTextField.setText("");
        moneyTextField.setDisable(true);
        classificationComboBox.getItems().clear();
        classificationComboBox.setDisable(true);
        memoTextArea.setText("");
        memoTextArea.setDisable(true);
        datePickerText.getEditor().setText("");
        datePickerText.setDisable(true);
        alterButton.setDisable(true);
    }
​
    /**
     * “支出”单选按钮的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void outputRadioButtonEvent(ActionEvent actionEvent) {
        // 获取支出分类的所有信息
        List<Classification> classificationList = new ClassificationDao().selectByType("支出");
        // 实例化一个一维数组
        String[] classificationNames = new String[classificationList.size()];
        // 将查询得到的分类名称装到一维数组中
        for (int i = 0; i < classificationList.size(); i++) {
            classificationNames[i] = classificationList.get(i).getcName();
        }
        // 给下拉列表框添加选项
        publicTools.public_addComboBoxItems(classificationComboBox, classificationNames);
        // 获取单选按钮项
        selectedRadioButton = outputRadioButton.getText();
    }
​
    /**
     * “收入”单选按钮的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void inputRadioButtonEvent(ActionEvent actionEvent) {
        // 获取收入分类的所有信息
        List<Classification> classificationList = new ClassificationDao().selectByType("收入");
        // 实例化一个一维数组
        String[] classificationNames = new String[classificationList.size()];
        // 将查询得到的分类名称装到一维数组中
        for (int i = 0; i < classificationList.size(); i++) {
            classificationNames[i] = classificationList.get(i).getcName();
        }
        // 给下拉列表框添加选项
        publicTools.public_addComboBoxItems(classificationComboBox, classificationNames);
        // 获取单选按钮项
        selectedRadioButton = inputRadioButton.getText();
    }
​
    /**
     * ”分类“下拉列表框的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void classificationComboBoxEvent(ActionEvent actionEvent) {
        //只处理选中的状态
        selectedCoboboxItem = (String) classificationComboBox.getSelectionModel().selectedItemProperty().getValue();
    }

查询按钮的功能就是获取用户输入的序号,然后从数据库中查询得到的数据填充显示在各个组件中,同删除功能的那一节的查询是一样的,唯一不同的是本节是将数据用各个控件显示,其中有下拉列表框、单选按钮等,而删除那节只是将要删除的信息显示在一个标签中。

所以查询按钮的事件处理代码如下:

    /**
     * ”查询“按钮的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void checkButtonEvent(ActionEvent actionEvent) {
        // 实例化RecordDao
        RecordDao recordDao = new RecordDao();
        // 实例化ClassificationDao
        ClassificationDao classificationDao = new ClassificationDao();
​
        String id = idTextField.getText();
        // 判断用户是否输入要查询的序号
        if (id == null || id.equals("")) {
            SimpleTools.informationDialog(Alert.AlertType.WARNING, "警告", "警告", "要查询的ID不能为空!");
        } else {
            // 使用正则表达式判断用户输入是否是数字而不是字符串
            boolean bb = Pattern.compile("^[-\\+]?[\\d]*$").matcher(id).matches();
            if (bb) {
                Record checkedRecord = recordDao.selectRecordByIdAndUserId(Integer.parseInt(id), Session.getUser().getUserId());
                if (checkedRecord.getRecordType() == null && checkedRecord.getRecordClassification() == null) {
                    SimpleTools.informationDialog(Alert.AlertType.WARNING, "警告", "警告", "该项不存在,请重新输出序号!");
                    // 重置数据填充
//                    initialize();
                } else {
                    // 使界面组件可编辑
                    inputRadioButton.setDisable(false);
                    outputRadioButton.setDisable(false);
                    moneyTextField.setDisable(false);
                    classificationComboBox.setDisable(false);
                    memoTextArea.setDisable(false);
                    datePickerText.setDisable(false);
                    alterButton.setDisable(false);
​
                    // 设置界面的值
                    if (checkedRecord.getRecordType().equals("支出")) {
                        //设置类型
                        outputRadioButton.setSelected(true);
                    } else {
                        inputRadioButton.setSelected(true);
                    }
​
                    // 如果支出单选按钮被选中
                    if (outputRadioButton.isSelected()) {
                        // 查询支出分类所在的名称
                        List<Classification> classificationList = classificationDao.selectByType("支出");
                        // 实例化一个一维数组
                        String[] classificationNames = new String[classificationList.size()];
                        // 将查询得到的分类名称装到一维数组中
                        for (int i = 0; i < classificationList.size(); i++) {
                            classificationNames[i] = classificationList.get(i).getcName();
                        }
                        // 重新为下拉列表框赋予选项
                        classificationComboBox.setItems(FXCollections.observableArrayList((List) Arrays.asList(classificationNames)));
                    }
                    // 如果收入单选按钮被选中
                    if (inputRadioButton.isSelected()) {
                        // 查询支出分类所在的名称
                        List<Classification> classificationList = classificationDao.selectByType("收入");
                        // 实例化一个一维数组
                        String[] classificationNames = new String[classificationList.size()];
                        // 将查询得到的分类名称装到一维数组中
                        for (int i = 0; i < classificationList.size(); i++) {
                            classificationNames[i] = classificationList.get(i).getcName();
                        }
                        // 重新为下拉列表框赋予选项
                        classificationComboBox.setItems(FXCollections.observableArrayList((List) Arrays.asList(classificationNames)));
                    }
​
                    //设置金额
                    moneyTextField.setText(String.valueOf(checkedRecord.getRecordMoney()));
​
                    // 设置分类
                    String str = checkedRecord.getRecordClassification();
                    int index = 0;
                    if (checkedRecord.getRecordType().equals("支出")) {
                        List outputList = FXCollections.observableArrayList((List) classificationDao.selectByType("收入"));
                        for (int i = 0; i < outputList.size(); i++) {
                            if (str.equals(outputList.get(i))) {
                                index = i;
                            }
                        }
                        classificationComboBox.getSelectionModel().select(index);
                    }
                    if (checkedRecord.getRecordType().equals("收入")) {
                        List inputList = FXCollections.observableArrayList((List) classificationDao.selectByType("收入"));
                        for (int i = 0; i < inputList.size(); i++) {
                            if (str.equals(inputList.get(i))) {
                                index = i;
                            }
                        }
                        classificationComboBox.getSelectionModel().select(index);
                    }
                    //设置备注
                    memoTextArea.setText(checkedRecord.getRecordMemo());
                    //设置日期
                    datePickerText.setValue(LocalDate.parse(checkedRecord.getRecordDate()));
                }
            } else {
                SimpleTools.informationDialog(Alert.AlertType.WARNING, "警告", "警告", "序号应该为数字而不是字符串!");
            }
​
        }
    }

上面的代码虽然看着很多,其实本质上就是获取要进行修改的数据,然后将其显示在界面控件上,大部分代码都是解决将数据信息在控件上。

查询功能测试如下:

接下来就是更改功能了,又从界面上获取要修改的数据,将其更新到数据库即可。

所以更改按钮的事件代码如下:

    /**
     * ”更改“按钮的事件监听器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void alterButtonEvent(ActionEvent actionEvent) {
        // 序号
        int id = Integer.parseInt(idTextField.getText());
        //类型
        String type = "";
        if (inputRadioButton.isSelected()) {
            type = inputRadioButton.getText();
        } else if (outputRadioButton.isSelected()) {
            type = outputRadioButton.getText();
        }
        // 金额,把从文本框得到的string类型数据转换为float类型
        float money = Float.parseFloat(moneyTextField.getText());
        // 分类
        String classification = classificationComboBox.getSelectionModel().getSelectedItem().toString();
        // 备注
        String memo = memoTextArea.getText();
        // 日期
        String date = datePickerText.getValue().toString();
        // 将用户修改的数据封装到实体类中
        Record record = new Record(Session.getUser().getUserId(), id, type, money, classification, memo, date);
        // 实例化RecordDao对象
        RecordDao recordDao = new RecordDao();
        // 执行修改操作
        boolean b = recordDao.updateRecord(record);
        // 对修改结果进行判断
        if (b) {
            SimpleTools.informationDialog(Alert.AlertType.INFORMATION, "提示", "信息", "修改账目成功!");
        } else {
            SimpleTools.informationDialog(Alert.AlertType.ERROR, "提示", "错误", "修改账目失败!");
        }
    }

到此逻辑代码写完,运行程序,测试功能:

更新成功:

 

 

可搜索微信公众号【Java实例程序】或者扫描下方二维码关注公众号获取更多。

注意:在公众号后台回复【20200328】可获取本章的源码 。

 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值