本節概要
如果用戶想要自定義分類,那麼本節就是爲了實現該功能,使得用戶能夠自定義收入和支出分類。
創建界面
首先在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】可獲取本章的源碼。