Java實戰之管家婆記賬系統(20)——添加分類界面及功能實現

本節概要

如果用戶想要自定義分類,那麼本節就是爲了實現該功能,使得用戶能夠自定義收入和支出分類。

 

創建界面

首先在view包下創建addClassificationFrame.fxml文件,使用Scene Builder來設計界面,界面中的各個組件的屬性和事件方法可以參考下面的代碼:

<?xml version="1.0" encoding="UTF-8"?>
​
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane prefHeight="517.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="AccountSystem.controller.AddClassificationFrameController">
    <children>
        <TabPane prefHeight="517.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE">
            <tabs>
                <Tab text="支出分類">
                    <content>
                        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                            <children>
                                <VBox prefHeight="481.0" prefWidth="600.0" spacing="30.0">
                                    <children>
                                        <Label text="添加支出分類" textFill="#7d7d7d">
                                            <font>
                                                <Font size="20.0"/>
                                            </font>
                                        </Label>
                                        <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0"
                                              spacing="20.0">
                                            <children>
                                                <Label text="分類名稱">
                                                    <font>
                                                        <Font size="28.0"/>
                                                    </font>
                                                </Label>
                                                <TextField fx:id="outputClassificationNameTextField"
                                                           promptText="輸入支出分類名稱">
                                                    <font>
                                                        <Font size="26.0"/>
                                                    </font>
                                                </TextField>
                                            </children>
                                        </HBox>
                                        <HBox alignment="CENTER" prefHeight="62.0" prefWidth="600.0">
                                            <children>
                                                <Button fx:id="addOutputButton" mnemonicParsing="false"
                                                        onAction="#addOutputButtonEvent" prefHeight="42.0"
                                                        prefWidth="216.0" text="添加支出">
                                                    <font>
                                                        <Font size="21.0"/>
                                                    </font>
                                                </Button>
                                            </children>
                                        </HBox>
                                        <Label text="支出分類列表" textFill="#7d7d7d">
                                            <font>
                                                <Font size="20.0"/>
                                            </font>
                                        </Label>
                                        <ListView fx:id="outputClassificationListView"
                                                  onEditCommit="#outputClassificationListViewCommitEvent"
                                                  prefHeight="250.0" prefWidth="600.0">
                                            <contextMenu>
                                                <ContextMenu>
                                                    <items>
                                                        <MenuItem fx:id="output_editContextMenu" mnemonicParsing="false"
                                                                  onAction="#output_editContextMenuEvent" text="編輯"/>
                                                        <MenuItem fx:id="output_deleteMenuItem" mnemonicParsing="false"
                                                                  onAction="#output_deleteMenuItemEvent" text="刪除"/>
                                                    </items>
                                                </ContextMenu>
                                            </contextMenu>
                                        </ListView>
                                        <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
                                            <children>
                                                <Button fx:id="outputClassificationReturnButton" mnemonicParsing="false"
                                                        onAction="#outputClassificationReturnButtonEvent" text="返回">
                                                    <font>
                                                        <Font size="21.0"/>
                                                    </font>
                                                </Button>
                                            </children>
                                        </HBox>
                                    </children>
                                </VBox>
                            </children>
                        </AnchorPane>
                    </content>
                </Tab>
                <Tab text="收入分類">
                    <content>
                        <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                            <children>
                                <VBox prefHeight="480.0" prefWidth="600.0" spacing="30.0">
                                    <children>
                                        <Label text="添加收入分類" textFill="#7d7d7d">
                                            <font>
                                                <Font size="20.0"/>
                                            </font>
                                        </Label>
                                        <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0"
                                              spacing="20.0">
                                            <children>
                                                <Label text="分類名稱">
                                                    <font>
                                                        <Font size="28.0"/>
                                                    </font>
                                                </Label>
                                                <TextField fx:id="inputClassificationNameTextField"
                                                           promptText="輸入收入分類名稱">
                                                    <font>
                                                        <Font size="26.0"/>
                                                    </font>
                                                </TextField>
                                            </children>
                                        </HBox>
                                        <HBox alignment="CENTER" prefHeight="62.0" prefWidth="600.0">
                                            <children>
                                                <Button fx:id="addInputButton" mnemonicParsing="false"
                                                        onAction="#addInputButtonEvent" prefHeight="42.0"
                                                        prefWidth="216.0" text="添加收入">
                                                    <font>
                                                        <Font size="21.0"/>
                                                    </font>
                                                </Button>
                                            </children>
                                        </HBox>
                                        <Label text="收入分類列表" textFill="#7d7d7d">
                                            <font>
                                                <Font size="20.0"/>
                                            </font>
                                        </Label>
                                        <ListView fx:id="inputClassificationListView"
                                                  onEditCommit="#inputClassificationListViewCommitEvent"
                                                  prefHeight="250.0" prefWidth="600.0">
                                            <contextMenu>
                                                <ContextMenu>
                                                    <items>
                                                        <MenuItem fx:id="input_editContextMenu" mnemonicParsing="false"
                                                                  onAction="#input_editContextMenuEvent" text="編輯"/>
                                                        <MenuItem fx:id="input_deleteContextMenu"
                                                                  mnemonicParsing="false"
                                                                  onAction="#input_deleteContextMenuEvent" text="刪除"/>
                                                    </items>
                                                </ContextMenu>
                                            </contextMenu>
                                        </ListView>
                                        <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
                                            <children>
                                                <Button fx:id="inputClassificationReturnButton" mnemonicParsing="false"
                                                        onAction="#inputClassificationReturnButtonEvent" text="返回">
                                                    <font>
                                                        <Font size="21.0"/>
                                                    </font>
                                                </Button>
                                            </children>
                                        </HBox>
                                    </children>
                                </VBox>
                            </children>
                        </AnchorPane>
                    </content>
                </Tab>
            </tabs>
        </TabPane>
    </children>
</AnchorPane>

接着是在controller創建與之對應的控制器類AddClassificationFrameController.java,bong從Scene Builder中複製該界面中的組件對象和事件方法的代碼到該類中:

package AccountSystem.controller;
​
import AccountSystem.bean.Classification;
import AccountSystem.dao.ClassificationDao;
import AccountSystem.tools.SimpleTools;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.stage.Stage;
​
import java.util.List;
​
/**
 * 添加分類界面控制器
 *
 * @author lck100
 */
public class AddClassificationFrameController {
    private ClassificationDao classificationDao = new ClassificationDao();
​
    private Stage dialogStage;
​
    public Stage getDialogStage() {
        return dialogStage;
    }
​
    public void setDialogStage(Stage dialogStage) {
        this.dialogStage = dialogStage;
    }
​
    @FXML
    private TextField inputClassificationNameTextField;
​
    @FXML
    private ListView<String> inputClassificationListView;
​
    @FXML
    private TextField outputClassificationNameTextField;
​
    @FXML
    private ListView<String> outputClassificationListView;
​
​
    /**
     * ”添加支出“按鈕的事件監聽器
     *
     * @param event 事件
     */
    public void addOutputButtonEvent(ActionEvent event) {
       
    }
​
    /**
     * “支出”右鍵菜單“編輯”的事件監聽器
     *
     * @param event 事件
     */
    public void output_editContextMenuEvent(ActionEvent event) {
       
    }
​
    /**
     * “支出”右鍵菜單“刪除”的事件監聽器
     *
     * @param event 事件
     */
    public void output_deleteMenuItemEvent(ActionEvent event) {
       
    }
​
    /**
     * 支出分類界面”返回“按鈕的事件監聽器
     *
     * @param event 事件
     */
    public void outputClassificationReturnButtonEvent(ActionEvent event) {
       
    }
​
    /**
     * ”添加收入“按鈕的事件監聽器
     *
     * @param event 事件
     */
    public void addInputButtonEvent(ActionEvent event) {
       
    }
​
    /**
     * “收入”右鍵菜單“編輯”的事件監聽器
     *
     * @param event 事件
     */
    public void input_editContextMenuEvent(ActionEvent event) {
       
    }
​
    /**
     * “收入”右鍵菜單“刪除”的事件監聽器
     *
     * @param event 事件
     */
    public void input_deleteContextMenuEvent(ActionEvent event) {
        
    }
​
    /**
     * 收入分類界面”返回“按鈕的事件監聽器
     *
     * @param event 事件
     */
    public void inputClassificationReturnButtonEvent(ActionEvent event) {
        
    }
​
    /**
     * “支出”分類列表視圖編輯完成的事件監聽器
     *
     * @param stringEditEvent 事件
     */
    public void outputClassificationListViewCommitEvent(ListView.EditEvent<String> stringEditEvent) {
       
    }
​
    /**
     * 收入分類列表視圖編輯完成的事件監聽器,按回車鍵完成對事件的響應
     *
     * @param stringEditEvent 事件
     */
    public void inputClassificationListViewCommitEvent(ListView.EditEvent<String> stringEditEvent) {
       
    }
​
}

其中的”getDialogStage()”和“setDialogStage()”就是將Stage傳到該類中,然後在“返回”按鈕事件中調用進行關閉窗口界面。

接着是在MainApp.java中創建方法加載FXML文件:

    /**
     * 操作結果:”添加分類“查詢結果界面
     */
    public Scene initAddClassificationFrame() {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(MainApp.class.getResource("view/addClassificationFrame.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);
​
            AddClassificationFrameController controller = loader.getController();
            controller.setDialogStage(mainFrameStage);
​
            mainFrameStage.showAndWait();
            return scene;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

最後是在菜單項事件中調用該方法:

    /**
     * ”添加分類“菜單項的事件監聽器
     *
     * @param actionEvent 事件
     */
    @FXML
    public void addClassificationMenuItemEvent(ActionEvent actionEvent) {
        // 打開添加分類界面
        mainApp.initAddClassificationFrame();
    }

運行項目,查看創建完成的界面:

 

實現功能

首先在“支出分類列表”和“收入分類列表”中顯示所有已存在的分類名稱,即初始化列表項在initialize()方法中:

    /**
     * 初始化界面
     */
    public void initialize() {
        // 獲取收入分類的所有信息
        List<Classification> inputClassificationList = new ClassificationDao().selectByType("收入");
        // 實例化一個一維數組
        String[] inputClassificationNames = new String[inputClassificationList.size()];
        // 將查詢得到的分類名稱裝到一維數組中
        for (int i = 0; i < inputClassificationList.size(); i++) {
            inputClassificationNames[i] = inputClassificationList.get(i).getcName();
        }
        inputClassificationListView.setItems(FXCollections.observableArrayList(inputClassificationNames));
​
        // 獲取支出分類的所有信息
        List<Classification> outputClassificationList = new ClassificationDao().selectByType("支出");
        // 實例化一個一維數組
        String[] outputClassificationNames = new String[outputClassificationList.size()];
        // 將查詢得到的分類名稱裝到一維數組中
        for (int i = 0; i < outputClassificationList.size(); i++) {
            outputClassificationNames[i] = outputClassificationList.get(i).getcName();
        }
        outputClassificationListView.setItems(FXCollections.observableArrayList(outputClassificationNames));
    }

下面就是實現“添加”功能了,通過界面上的“添加支出”和“添加收入”來實現,獲取界面用戶輸入的分類名稱,然後將其插入到數據庫表中並且下面的列表也進行更新顯示。

所以“添加支出”按鈕的事件監聽器代碼如下:

    /**
     * ”添加支出“按鈕的事件監聽器
     *
     * @param event 事件
     */
    public void addOutputButtonEvent(ActionEvent event) {
        // 獲取用戶輸入的支出分類名稱
        String output = outputClassificationNameTextField.getText();
        // 判斷用戶是否輸入爲空
        if (null == output || "".equals(output)) {
            SimpleTools.informationDialog(Alert.AlertType.WARNING, "提示", "警告", "文本框內容不能爲空!");
        } else {
            // 列表視圖添加用戶輸入的支出分類重名
            outputClassificationListView.getItems().add(output);
            // 封裝要添加的分類實體類數據
            Classification classification = new Classification(output, "支出");
            // 進行添加操作
            boolean b = classificationDao.addClassification(classification);
            outputClassificationNameTextField.setText("");
        }
​
    }

“添加收入”按鈕的事件監聽器代碼如下:

    /**
     * ”添加收入“按鈕的事件監聽器
     *
     * @param event 事件
     */
    public void addInputButtonEvent(ActionEvent event) {
        // 獲取用戶輸入的收入分類
        String input = inputClassificationNameTextField.getText();
        // 判斷用戶是否輸入爲空
        if (null == input || "".equals(input)) {
            SimpleTools.informationDialog(Alert.AlertType.WARNING, "提示", "警告", "文本框內容不能爲空!");
        } else {
            // 向列表視圖添加收入分類
            inputClassificationListView.getItems().add(input);
            // 向數據庫中添加收入分類
            classificationDao.addClassification(new Classification(input, "收入"));
            // 清空用戶輸入
            inputClassificationNameTextField.setText("");
        }
    }

“返回”按鈕的功能是退出這個界面,即關閉該Stage,方法代碼如下:

    /**
     * 支出分類界面”返回“按鈕的事件監聽器
     *
     * @param event 事件
     */
    public void outputClassificationReturnButtonEvent(ActionEvent event) {
        // 關閉該界面
        dialogStage.close();
    }
​
    /**
     * 收入分類界面”返回“按鈕的事件監聽器
     *
     * @param event 事件
     */
    public void inputClassificationReturnButtonEvent(ActionEvent event) {
        dialogStage.close();
    }

除了添加分類之外,肯定還有刪除和編輯分類。

刪除分類就是在列表視圖中選中要刪除的列表項,然後右鍵單擊選中刪除,即可刪除該項並從數據庫中也進行 刪除。

所以“支出分類”界面的“刪除”右鍵菜單事件方法如下:

    /**
     * “支出”右鍵菜單“刪除”的事件監聽器
     *
     * @param event 事件
     */
    public void output_deleteMenuItemEvent(ActionEvent event) {
        // 獲取用戶選中的支出分類
        String outputItem = (String) outputClassificationListView.getSelectionModel().getSelectedItem();
        // 確認用戶是否要刪除
        boolean b = SimpleTools.informationDialog(Alert.AlertType.CONFIRMATION, "確認", "確認", "請問是否確認刪除名爲" + outputItem + "的支出分類?");
        if (b) {
            // 從列表視圖中移除該分類
            outputClassificationListView.getItems().remove(outputItem);
            // 從數據庫中刪除該分類
            classificationDao.deleteClassification(new Classification(outputItem, "支出"));
        }
    }

“收入分類“界面的”刪除“右鍵菜單事件方法如下:

    /**
     * “收入”右鍵菜單“刪除”的事件監聽器
     *
     * @param event 事件
     */
    public void input_deleteContextMenuEvent(ActionEvent event) {
        // 獲取用戶輸入的收入分類
        String inputItem = (String) inputClassificationListView.getSelectionModel().getSelectedItem();
        boolean b = SimpleTools.informationDialog(Alert.AlertType.CONFIRMATION, "確認", "確認", "請問是否確認刪除名爲" + inputItem + "的收入分類?");
        if (b) {
            // 向列表視圖中移除該收入分類
            inputClassificationListView.getItems().remove(inputItem);
            // 向數據庫中刪除該收入分類
            classificationDao.deleteClassification(new Classification(inputItem, "收入"));
        }
    }

而編輯列表項稍微要難些,先要通過右鍵菜單“編輯”使列表項可以編輯,然後通過“ListView.EditEvent<String>”事件來獲取修改後的值進行更新操作。

所以“支出分類”界面的編輯事件代碼如下:

    /**
     * “支出”右鍵菜單“編輯”的事件監聽器
     *
     * @param event 事件
     */
    public void output_editContextMenuEvent(ActionEvent event) {
        outputClassificationListView.setCellFactory(TextFieldListCell.forListView());
        outputClassificationListView.setEditable(true);
        outputClassificationListView.setFocusTraversable(true);
    }
​
    /**
     * “支出”分類列表視圖編輯完成的事件監聽器
     *
     * @param stringEditEvent 事件
     */
    public void outputClassificationListViewCommitEvent(ListView.EditEvent<String> stringEditEvent) {
        // 獲取列表視圖選中的原值
        String sourceValue = stringEditEvent.getSource().getSelectionModel().getSelectedItem();
        // 獲取列表視圖編輯後的新值
        String newValue = stringEditEvent.getNewValue();
        // 向列表視圖移除原值
        outputClassificationListView.getItems().remove(sourceValue);
        // 向列表視圖添加新值
        outputClassificationListView.getItems().add(newValue);
        // 向數據庫更新值
        classificationDao.updateClassification(newValue, sourceValue);
    }

“收入分類“界面中的編輯事件代碼如下:

    /**
     * “收入”右鍵菜單“編輯”的事件監聽器
     *
     * @param event 事件
     */
    public void input_editContextMenuEvent(ActionEvent event) {
        inputClassificationListView.setCellFactory(TextFieldListCell.forListView());
        inputClassificationListView.setEditable(true);
        inputClassificationListView.setFocusTraversable(true);
    }
    
        /**
     * 收入分類列表視圖編輯完成的事件監聽器,按回車鍵完成對事件的響應
     *
     * @param stringEditEvent 事件
     */
    public void inputClassificationListViewCommitEvent(ListView.EditEvent<String> stringEditEvent) {
        // 獲取列表視圖選中的原值
        String sourceValue = stringEditEvent.getSource().getSelectionModel().getSelectedItem();
        // 獲取列表視圖編輯後的新值
        String newValue = stringEditEvent.getNewValue();
        // 向列表視圖移除原值
        inputClassificationListView.getItems().remove(sourceValue);
        // 向列表視圖添加新值
        inputClassificationListView.getItems().add(newValue);
        // 向數據庫更新值
        classificationDao.updateClassification(newValue, sourceValue);
    }

添加分類界面的邏輯功能已經實現,能夠完成對分類的增加、刪除和編輯。

運行代碼,測試功能:

 

 

可搜索微信公衆號【Java實例程序】或者掃描下方二維碼關注公衆號獲取更多。

注意:在公衆號後臺回覆【20200421】可獲取本章的源碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章