0

I developed a simple demo JavaFx app with Sqlite since command line(terminal) with two tabs (tab1-Info and tab2-Register), in tab1-Info there is a tableview "myTable" that shows only id, name and lastname and in tab2-Register shows the textfields to register name and lastname as seen in the following figures.

enter image description hereenter image description here

In the archives i use tab1.fxml and tab2.fxml which tab1 calls Controller.java and tab2.fxml calls Tab2Controller.java. Actually the simple demo JavaFx app with Sqlite is working perfectly, but i do not know how to refresh tableview "myTable" when i pressed the button "save" which is in another controller tab2.fxml (Tab2Controller.java) different from where tab1-info TableView "myTable" is located. I wish that when i pressed the button "save", automatically "myTable" updates/refresh the new content data, any advice in order to solve this issue?

Here are the java program archives.

principal.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class principal extends Application {
    
    public static void main(String[] args) {
        Application.launch(principal.class, args);
    }
    
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("scheme.fxml"));
        
        stage.setTitle("Demo tab version");
        stage.setScene(new Scene(root, 300, 400));
        stage.show();
    }
}

scheme.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>


 <GridPane  xmlns:fx="http://javafx.com/fxml"  hgap="20" vgap="20" styleClass="root" gridLinesVisible="false">
 
  <padding><Insets top="25" right="2" bottom="20" left="2" /></padding>
 
  <Text id="welcome-text" text="Demo tab" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="6" GridPane.rowSpan="1"/>
 
<TabPane fx:id="tabPane" xmlns:fx="http://javafx.com/fxml" prefHeight="500.0" prefWidth="300.0" GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.columnSpan="6" tabClosingPolicy="UNAVAILABLE">
    <tabs>
        <Tab fx:id="tab1" text="Info" >
     
             <fx:include source="Tab1.fxml"/>
        </Tab>
        <Tab fx:id="tab2" text="Register" >
               
             <fx:include source="Tab2.fxml"/>
        </Tab>
    </tabs>
    
    </TabPane>
    
  <stylesheets>
    <URL value="@Login.css" />
  </stylesheets>

Tab1.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.cell.*?>

 <GridPane fx:controller="Controller" xmlns:fx="http://javafx.com/fxml"  hgap="20" vgap="20" >


     <!--  <ScrollPane  visible="true" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="1" GridPane.rowSpan="5">  -->
       
       <VBox layoutX="15.0" layoutY="76.0" prefHeight="528.0" prefWidth="1200.0">
         <children>
            <TableView fx:id="myTable" prefHeight="512.0" prefWidth="500.0" />
         </children>
      </VBox>
     
 

</GridPane>  

Tab2.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.Label?>

 <GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="Tab2Controller" hgap="10" vgap="5">




<Text id="informacion" text="Personal Information" GridPane.columnIndex="1" GridPane.rowIndex="0" style="-fx-fill:white" />

<Text text="Name" GridPane.columnIndex="1" GridPane.rowIndex="2" style="-fx-fill:white"/>
 <TextField fx:id="name" GridPane.columnIndex="1" GridPane.rowIndex="3" prefWidth="150.0"/>
 
 <Text text="Lastname" GridPane.columnIndex="1" GridPane.rowIndex="4" style="-fx-fill:white" />
 <TextField fx:id="lastname" GridPane.columnIndex="1" GridPane.rowIndex="5" prefWidth="300.0" />
 
     
         <Button text="Save" GridPane.columnIndex="1" GridPane.rowIndex="7" prefHeight="20" prefWidth="90" GridPane.halignment="RIGHT" onAction="#handleSubmitButtonAction"/>

</GridPane>  

Controller.java

import java.sql.*;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.sql.Connection;  
 import java.sql.ResultSet;   
 import java.sql.DriverManager;  
 import java.sql.SQLException;  
 import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

   
   public class Controller implements Initializable{ 

     @FXML
    public TableView myTable;
    
     @Override
    public void initialize(URL url, ResourceBundle rb) {
    
      TableColumn<Integer, Person> column1 = new TableColumn<>("Id");
        column1.setCellValueFactory(new PropertyValueFactory<>("id"));
        
         TableColumn<String, Person> column2 = new TableColumn<>("Name");
        column2.setCellValueFactory(new PropertyValueFactory<>("nomCom"));
        TableColumn<String, Person> column3 = new TableColumn<>("LastName");
        column3.setCellValueFactory(new PropertyValueFactory<>("ApellPatern"));
        
          myTable.getColumns().add(column1);
        myTable.getColumns().add(column2);
        myTable.getColumns().add(column3);
        
             String sql = "SELECT id, nomCom, ApellPatern  FROM warehouses";
        
          try (Connection conn = this.connect();
             Statement stmt  = conn.createStatement();
             ResultSet rs    = stmt.executeQuery(sql)){
          
           System.out.println("Opened database successfully");
            while (rs.next()) { 
                System.out.println(rs.getInt("id")+ "\t" + rs.getString("nomCom") +  "\t" + rs.getString("ApellPatern"));   
     
    myTable.getItems().add(new Person(rs.getInt("id"),rs.getString("nomCom"),rs.getString("ApellPatern")));            
                
       }/*Aqui finaliza el while */
             /*Aqui finaliza el executequery*/
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
      
    }/* End of initialize */
    
     public class Person {
    
     private Integer id=null;
     private String nomCom=null;
    private String ApellPatern=null;
    
    public Person(Integer id, String nomCom, String ApellPatern){
    this.id=id;
    this.nomCom=nomCom;
    this.ApellPatern=ApellPatern;
    }
    
     public Integer getId(){
          return id;
   }
    
   
 public String getNomCom() {
        return nomCom;
    }
    
public String getApellPatern(){
    return ApellPatern;
    }
    
    }
        
        
          private  Connection connect() {
         String url ="jdbc:sqlite:test.db";
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return conn;
    }
   

}

Tab2Controller.java

import java.sql.*;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.sql.Connection;  
 import java.sql.ResultSet;   
 import java.sql.DriverManager;  
 import java.sql.SQLException;  
 import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import java.sql.SQLException;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Alert;

public class Tab2Controller implements Initializable{ 

 
 /*@FXML private fx:id="name" */
  @FXML private TextField name;
  
   /*@FXML private fx:id="lastname" ;*/
  @FXML private TextField lastname;
  
   @Override
    public void initialize(URL url, ResourceBundle rb) {
    
    /* No information*/
     
    }
     
 @FXML protected void handleSubmitButtonAction(ActionEvent event) {
        
        String nomCom=name.getText();
        String ApellPatern=lastname.getText();
        
         String sql = "INSERT INTO warehouses(nomCom,ApellPatern) VALUES(?,?)";

        try (Connection conn = this.connect();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
          
            pstmt.setString(1,nomCom);
            pstmt.setString(2, ApellPatern);
          
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        
        Alert alert = new Alert(AlertType.INFORMATION);
        alert.setTitle("Information Dialog");
        alert.setHeaderText(null);
        alert.setContentText("The information has been saved succesfully");

        alert.showAndWait();
        
    }
    
    private Connection connect() {
        // SQLite connection string
      //  String url = "jdbc:sqlite:C://sqlite/db/test.db";
         String url ="jdbc:sqlite:test.db";
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return conn;
    }

   
}

Any help is appreciated. Thank you in advance

  • how can i implement a myTable.refresh(); since Tab2Controller.java? – Omar Elio Torres Castillo Dec 06 '21 at 06:00
  • You don't need to add questions or extra info in comments, you can edit the question to do that. – jewelsea Dec 06 '21 at 06:48
  • 3
    You should never really need to call `refresh()` on a table, it will automatically update when the underlying list updates. You should update the underlying list. For that, see [applying MVC](https://stackoverflow.com/questions/32342864/applying-mvc-with-javafx) (or the Eden tutorial linked in that answer). This question may be closed as a duplicate of that question. – jewelsea Dec 06 '21 at 06:51
  • If you only need to update when adding/removing items, then you don't need an extractor. If you wanted to update, for example, a name property value within an existing table row item, then you need an [extractor](https://stackoverflow.com/questions/31687642/callback-and-extractors-for-javafx-observablelist). – jewelsea Dec 06 '21 at 06:55
  • 1
    Common IDEs like idea have simple tools for [formatting code](https://www.jetbrains.com/help/idea/reformat-and-rearrange-code.html#reformat_code), it is a nice idea to apply them to code (including fxml) you post online, as it makes it much easier to read. – jewelsea Dec 06 '21 at 06:58
  • Excuse me, thank you very much for your answer, i am new in JavaFx, and i don't have any idea what is MVC, i will search information about it, thank you – Omar Elio Torres Castillo Dec 06 '21 at 07:21
  • 2
    [MVC in general](https://en.wikipedia.org/wiki/Model–view–controller) is a loosely defined pattern used in software design, it is not specific to JavaFX. Related is [MVVM](https://en.wikipedia.org/wiki/Model–view–viewmodel). The best (practical) description of MVC applied to JavaFX is (I think) the [eden tutorial](https://edencoding.com/mvc-in-javafx/). I guess then, the suggestion is to study it and try it, and, if you get stuck, come back with an updated [mcve] in a new question. – jewelsea Dec 06 '21 at 07:36
  • You are using JavaFX+SQLLite, [eden has a tutorial on that too](https://edencoding.com/connect-javafx-with-sqlite/), if you need it. That tutorial actually applies the MVC principle to data access for a table in SQLLite which is editable by a separate dialog, so the whole thing is very close to what you are trying to do. Source in [github](https://github.com/edencoding/javafx-io/tree/master/sqlite). I don't normally recommend external code sources, but in this case, I think it is a good idea to do so. – jewelsea Dec 06 '21 at 07:36
  • this question is faaar too broad (f.i. the use table.refresh, communication between controllers, hooking into backend) - strip it down to a single problem, write a [mcve] demonstrating what's wrong with that (as already suggested by @jewelsea) . Repeat and rinse with the next part. Only when you are confident with each in isolation, start to combine :) – kleopatra Dec 06 '21 at 11:21
  • Unfortunatelly, i solved this issue that i had in this program which is "not" using different tab.fxml archives (Tab1.fxml,Tab2.fxml,etc), to solve this, i just used one fxml archive and only one controller, and after that i use myTable.getItems().clear(); and i loaded the data again to the tableView in order to update data, this works perfectly!!!, but not with different fxml archives separated, anyways Now i am interested in learning MVC, thank you very much for the help – Omar Elio Torres Castillo Dec 07 '21 at 07:37

0 Answers0