我如何从一个JavaFX选项卡中添加到数据库,以反映在另一个JavaFX选项卡中?

问题描述 投票:1回答:1

我有一个围绕JavaFXML,scenebuilder和Derby数据库构建的简单的两标签应用程序。有一个MainController类声明为:

package tabpane.view;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;

public class MainController {
  @FXML public TabPane tabPane;
  @FXML public Tab inputTab;
  @FXML public Tab accountTab;
  @FXML private Button exitBtn;

  @FXML private void handleExitBtn() {
    System.exit(0);
  }
}

InputController类定义名为Input的第一个选项卡。它封送一些基本数据,包括一个新的帐户名和一个复选框,以指示该帐户是否处于活动状态。收集输入后,将通过DAO控制器类将其写入derby数据库的表中:

package tabpane.view;

import java.net.URL;
import java.sql.SQLException;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TextField;
import tabpane.db.NdDao;
import tabpane.model.AccountObject;

public class InputController implements Initializable
{
  @FXML private TextField accName;
  @FXML private CheckBox isEnabled;
  @FXML private Button saveBtn;  

  @Override
  public void initialize(URL location, ResourceBundle resources) {}

  @FXML private void handleSaveBtn() throws SQLException {
    AccountObject obj = new AccountObject(accName.getText(), isEnabled.isSelected());
    NdDao.connect();
    NdDao.insertAccount(obj);
    NdDao.disconnect();
  }
}

这是DAO控制器类中的代码:

package tabpane.db;

import tabpane.model.AccountObject;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.TreeMap;

public class NdDao 
{  
  private static final String strAccountInsert = "INSERT INTO ACCOUNTS " +
            "   (ACCNAME, ISENABLED) " + "VALUES (?, ?)";
  private static final String strAccountSelectAll = "SELECT * from ACCOUNTS ORDER BY ACCNAME ASC";

  private static PreparedStatement pstmtAccountInsert;
  private static PreparedStatement pstmtAccountSelectAll;

  private static Connection conn = null;

  public static void connect() throws SQLException {
    conn = DriverManager.getConnection("jdbc:derby:C:/Users/" + System.getenv("USERNAME") + "/AppData/Local/TabPaneEx/db" + ";create=true");
    prepareStatements();
  } 

  public static void disconnect() throws SQLException {
    if (conn != null) {
      conn.close();
      conn = null;
    }
  }

  private static void prepareStatements() throws SQLException{
    pstmtAccountInsert  = conn.prepareStatement(strAccountInsert);
    pstmtAccountSelectAll  = conn.prepareStatement(strAccountSelectAll);
  }

  public static void insertAccount(AccountObject obj) throws SQLException
  {  
    pstmtAccountInsert.clearParameters();        
    pstmtAccountInsert.setString(1, obj.getAccName());
    pstmtAccountInsert.setBoolean(2, obj.getIsEnabled());
    pstmtAccountInsert.executeUpdate();         
  }

  public static TreeMap<Integer, AccountObject> selectAccounts() throws SQLException        {
    TreeMap<Integer, AccountObject> map = new TreeMap<>();
    ResultSet results;
    AccountObject obj;
    results = pstmtAccountSelectAll.executeQuery();    
    while(results.next()) {
      obj = new AccountObject(
                results.getString(1),
                results.getBoolean(2)
      );
      map.put( (obj.hashCode() ), obj);       
    } 
    return map;
  }

}

DetailController类定义了第二个选项卡。在此类中,通过DAO从数据库中初始化帐户名组合框:

package tabpane.view;

import java.net.URL;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.AnchorPane;
import tabpane.db.NdDao;
import tabpane.model.AccountObject;

public class DetailController implements Initializable
{
  @FXML public ComboBox<String> accNames;

  @Override
  public void initialize(URL location, ResourceBundle resources) {
    try {
      getAccCBoxView();
    } catch (SQLException ex) {
      Logger.getLogger(DetailController.class.getName()).log(Level.SEVERE, null, ex);
    }
    accNames.getSelectionModel().select(0);
  }

  public void getAccCBoxView() throws SQLException
  {
    ObservableList<String> list = FXCollections.observableArrayList();
    NdDao.connect();//
    TreeMap<Integer, AccountObject> map = NdDao.selectAccounts() ;
    NdDao.disconnect();//
    AccountObject obj ;
    Iterator<AccountObject> li = map.values().iterator();
    while (li.hasNext()){
      obj = li.next();
      list.add(obj.getAccName());
    }
    accNames.setItems(list);
  } 
}

首先,在数据库表“ L Enqvist”中只有一个条目。在详细信息选项卡组合框中,如下所示:Fig 1

图1。

然后我通过输入选项卡输入新名称,然后按保存:Fig 2

图2

ACCOUNTS表的转储显示添加成功:

ACCNAME ISENABLED
L Enqvist   false
K Berg      false

[如果我再单击“帐户”选项卡,希望在组合框中找到它:Fig 3图3。

但是,组合框没有更新,我所看到的只是图1中的视图。我真的不知道如何进行操作,将不胜感激一些指针,也许是使代码按预期工作所需的代码或某些具体参考信息。到目前为止,我在互联网上的大量搜索中都找不到任何东西,并且想知道这种实现是否实际上是可能的。

java javafx combobox auto-update
1个回答
0
投票

auto-update组合框项目有几种方法,

第一种方法:在帐户标签选项卡上设置一个EventHandler,加载数据并将项目设置到您的帐户组合框中。

首先,您需要将DetailController加载到MainController中,因为您具有用于详细视图布局的单独控制器。然后在帐户标签上添加EventHandler,以侦听您的标签点击并重新加载ComboBox项目的最新数据。

public class MainController implements Initializable    {
    @FXML public TabPane tabPane;
    @FXML public Tab inputTab;
    @FXML public Tab accountTab;
    @FXML private Button exitBtn;

    private DetailController detailController;      

    @Override
    public void initialize(URL location, ResourceBundle resources) {            
        detailController = new FXMLLoader(getClass().getResource("/path/account-detail.fxml")).getController();         
        accountTab.setOnSelectionChanged(event -> reloadAccounts());            
    }

    private void reloadAccounts() {
        try {
            detailController.getAccCBoxView();
        } catch (SQLException ex) {
            Logger.getLogger(MainController.class.getName()).log(Level.SEVERE, null, ex);
        }
        detailController.accNames.getSelectionModel().select(0);
    }

    @FXML private void handleExitBtn() {
        System.exit(0);
    }
}

第二种方法:在InputController中插入AccountObject时,在account-combo-box上添加一个项目

作为第一种方法,首先,您需要访问DetailController中的InputController,并将新的AccountObject直接添加到accNames ComboBox中。

public class InputController implements Initializable   {
    @FXML private TextField accName;
    @FXML private CheckBox isEnabled;
    @FXML private Button saveBtn;  

    private DetailController detailController;      

    @Override
    public void initialize(URL location, ResourceBundle resources) {        
        detailController = new FXMLLoader(getClass().getResource("/path/account-detail.fxml")).getController();     
    }

    @FXML private void handleSaveBtn() throws SQLException {
        AccountObject obj = new AccountObject(accName.getText(), isEnabled.isSelected());
        NdDao.connect();
        NdDao.insertAccount(obj);
        NdDao.disconnect();
        detailController.accNames.getItems().add(obj.getAccName());
    }
}

关于这些方法的更多要点,

  • 如果您拥有大量帐户,并且需要与数据库连接并在每次accountTab单击中重新加载数据,第一种方法都会有点昂贵。
  • 如果插入新的AccountObject得到FAILED],第二种方法似乎不合适。
  • 如果您的数据很少,我更喜欢使用第一种方法。
  • 此外,您可以通过修改代码来增强第二种方法。您可以添加新的AccountObject ONLY IF
  • 插入得到SUCCEED
© www.soinside.com 2019 - 2024. All rights reserved.