2017-01-22 32 views
0

我試圖在JavaFX中將類似金融組織者保存到數據庫中。我想從數據庫中檢索數據,並在按下收入按鈕後將其存儲在tableview中。起初沒有問題。舞臺改變,tableview將被填充。當我點擊返回按鈕,並且收入階段再次發生變化時,NullPointerException已在MainMenuController的db.selectIncome()行中發生。我不知道爲什麼會發生。有誰能夠幫助我?JavaFX,SQL,更改階段時發生錯誤

主類 package app;

import java.io.IOException; 

import controller.MainMenuController; 
import data.DataBase; 
import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 
import utils.SQLConnection; 
import utils.StageLoader; 

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) throws IOException { 
     FXMLLoader loader = new FXMLLoader(); 
     loader.setLocation(this.getClass().getResource("/fxml/MainMenu.fxml")); 
     Parent root = loader.load(); 

     Scene scene = new Scene(root); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     MainMenuController mainMenuController = loader.getController(); 
     mainMenuController.setStage(primaryStage); 

     SQLConnection.dataBaseConnection(); 
     DataBase db = new DataBase(); 
     StageLoader stageLoader = new StageLoader(); 
     mainMenuController.setDataBase(db); 
     mainMenuController.setStageLoader(stageLoader); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

MainMenuController

package controller; 

import java.io.IOException; 

import data.DataBase; 
import javafx.fxml.FXML; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.stage.Stage; 
import utils.StageLoader; 

public class MainMenuController { 

    public static final String INCOME_MENU_FXML = "/fxml/IncomeMenu.fxml"; 
    private Stage stage; 
    private StageLoader stageLoader; 
    private DataBase db; 

    public void setStage(Stage stage) { 
     this.stage = stage; 
    } 

    public void setStageLoader(StageLoader stageLoader) { 
     this.stageLoader = stageLoader; 
    } 

    public void setDataBase(DataBase db) { 
     this.db = db; 
    } 

    @FXML 
    public void goToIncomeMenu() throws IOException { 
     stageLoader = new StageLoader(); 
     stageLoader.loadStage(INCOME_MENU_FXML, stage); 
     IncomeMenuController incomeMenuController = stageLoader.getLoader().getController(); 
     incomeMenuController.setStage(stage); 

     db.selectIncome(); 

     incomeMenuController.getIncomeAmountColumn().setCellValueFactory(new PropertyValueFactory<>("amount"));; 
     incomeMenuController.getIncomeCategoryColumn().setCellValueFactory(new PropertyValueFactory<>("category")); 
     incomeMenuController.getIncomeDateColumn().setCellValueFactory(new PropertyValueFactory<>("stringDate")); 
     incomeMenuController.getIncomeTable().setItems(db.getBudget()); 


     incomeMenuController.setStageLoader(stageLoader); 
     incomeMenuController.setDataBase(db); 
    } 

    @FXML 
    public void exitApplication() { 
     System.exit(0); 
    } 

    @FXML 
    public void initialize() { 

    } 
} 

IncomeMenuController

package controller; 

import java.io.IOException; 

import data.Budget; 
import data.DataBase; 
import javafx.fxml.FXML; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.stage.Stage; 
import utils.StageLoader; 

public class IncomeMenuController { 

    public static final String ADD_INCOME_MENU_FXML = "/fxml/AddIncomeMenu.fxml"; 
    public static final String MAIN_MENU_FXML = "/fxml/MainMenu.fxml"; 
    private Stage stage; 
    private StageLoader stageLoader; 
    private Stage addIncomeStage; 
    private DataBase db; 

    public void setStageLoader(StageLoader stageLoader) { 
     this.stageLoader = stageLoader; 
    } 

    public void setStage(Stage stage) { 
     this.stage = stage; 
    } 

    public void setDataBase(DataBase db) { 
     this.db = db; 
    } 

    public TableView<Budget> getIncomeTable() { 
     return incomeTable; 
    } 

    public TableColumn<Budget, Double> getIncomeAmountColumn() { 
     return incomeAmountColumn; 
    } 

    public TableColumn<Budget, String> getIncomeCategoryColumn() { 
     return incomeCategoryColumn; 
    } 

    public TableColumn<Budget, String> getIncomeDateColumn() { 
     return incomeDateColumn; 
    } 

    @FXML 
    TableView<Budget> incomeTable; 

    @FXML 
    TableColumn<Budget, Double> incomeAmountColumn; 

    @FXML 
    TableColumn<Budget, String> incomeCategoryColumn; 

    @FXML 
    TableColumn<Budget, String> incomeDateColumn; 

    @FXML 
    public void goToAddIncomeMenu() throws IOException { 
     addIncomeStage = new Stage(); 
     stageLoader.loadStage(ADD_INCOME_MENU_FXML, addIncomeStage); 
     AddIncomeMenuController addIncomeMenuController = stageLoader.getLoader().getController(); 
     addIncomeMenuController.setStage(addIncomeStage); 
     addIncomeMenuController.setDataBase(db); 
    } 

    @FXML 
    public void goToMainMenu() throws IOException { 
     stageLoader.loadStage(MAIN_MENU_FXML, stage); 
     MainMenuController mainMenuController = stageLoader.getLoader().getController(); 
     mainMenuController.setStage(stage); 
     mainMenuController.setStageLoader(stageLoader); 
    } 

    @FXML 
    public void load() { 

    } 

    @FXML 
    public void initialize() { 

    } 
} 

數據庫

package data; 

import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.time.LocalDate; 
import java.time.format.DateTimeFormatter; 


import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.control.DatePicker; 

import javafx.scene.control.TextField; 

import utils.SQLConnection; 

public class DataBase { 

    private String query; 
    private PreparedStatement prepStmt; 
    private ResultSet result; 
    private DateTimeFormatter formatter; 
    private DateTimeFormatter tableColumnFormatter; 
    private Income income; 
    private ObservableList<Budget> budget; 

    public ObservableList<Budget> getBudget() { 
     return budget; 
    } 

    public DataBase() { 
     formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); 
     tableColumnFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); 
     income = new Income(); 
     budget = FXCollections.observableArrayList(); 
     System.out.println("utworzono obiekt bazy danych"); 
    } 

    public void addIncome(TextField amountField, TextField categoryField, DatePicker dateField) { 
     try { 
      query = "INSERT INTO Incomes(ID, Amount, Category, Date) VALUES (NULL, ?, ?, ?);"; 
      prepStmt = SQLConnection.getConnection().prepareStatement(query); 
      prepStmt.setDouble(1, Double.parseDouble(amountField.getText())); 
      prepStmt.setString(2, categoryField.getText()); 
      prepStmt.setString(3, dateField.getValue().format(formatter)); 
      prepStmt.execute(); 

      prepStmt.close(); 
     } catch (SQLException e) { 
      System.err.println("Błąd podczas dodawania do bazy danych"); 
      e.printStackTrace(); 
     } 
    } 

    public void selectIncome() { 
     budget.clear(); 
     try { 
      query = "SELECT * FROM Incomes;"; 
      prepStmt = SQLConnection.getConnection().prepareStatement(query); 
      result = prepStmt.executeQuery(); 
      while(result.next()) { 
       income.setAmount(result.getDouble("amount")); 
       income.setCategory(result.getString("category")); 
       income.setStringDate(result.getString("date")); 
       income.setDate(LocalDate.parse(income.getStringDate())); 
       income.setStringDate(income.getDate().format(tableColumnFormatter)); 
       budget.add(new Income(income.getAmount(), income.getCategory(), income.getStringDate())); 
      } 
      for(Budget i: budget) { 
       System.out.println(i); 
      } 
      prepStmt.close(); 
      result.close(); 
     } catch (SQLException e) { 
      System.err.println("Błąd podczas pobierania danych z bazy"); 
     } 

    } 
} 
+1

發佈您的堆棧跟蹤。 – Sedrick

+0

'NullPointerException'不是「SQL異常」。見例如在這裏:http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it –

回答

0

我想,當您單擊後退按鈕的代碼被執行。

@FXML 
public void goToMainMenu() throws IOException { 
    stageLoader.loadStage(MAIN_MENU_FXML, stage); 
    MainMenuController mainMenuController = stageLoader.getLoader().getController(); 
    mainMenuController.setStage(stage); 
    mainMenuController.setStageLoader(stageLoader); 
} 

以前,您是在控制器之間傳遞數據庫對象,但這次您沒有。

mainMenuController.setDataBase(db); 

而且由於db尚未初始化,努力做db.selectIncome()拋出一個NullPointerException

作爲一個方面說明,您應該儘可能避免創建新的Stage對象。在你的情況下,切換Scene或更改其內容就足夠了,因爲你只是改變窗口的外觀 - 你不需要另外一個窗口。 Here's這樣做的方法之一。

+0

是的,這是問題。我糾正了這個方法,現在它工作。感謝您的建議:)還有一個問題。什麼是SceneBuilder中的按鈕或setOnAction/ActionEvent的更常見的方法? – bartekms274

+0

通過避免創建新階段,您的意思是在IncomeMenuController中的goToAddIncomeMenu()方法?因爲通過setStage方法,我總是通過控制器傳遞相同的舞臺對象?我對嗎? – bartekms274

+0

不客氣:)我不使用Scene Builder,但就我而言,它會創建需要綁定控制器的FXML文件。這對我來說是一個首選的方式,因爲它可以方便地將視圖從邏輯中分離出來......但這只是我,我不知道哪種方式更受歡迎或更好。兩者都是可行的。 – Dth