I'm trying to create a search bar with a listener to perform real-time searching and filtering of data in javafx. The dataSearch method should be triggered when I click the execute button that starts the program. Initially, my search bar seems to be working fine, but the issue is that when I update my Oracle's database from the application, the TableView stops getting filtered by the input keyword from the search bar. It seems that the dataSearch method is only invoked once every time the program is executed, and after the TableView is modified, the ObservableList called generalList doesn't automatically get updated.
Code example:
public class App extends Application { private TableView<General> generalTableView; private ObservableList<General> generalList; private TextField searchBox; private TextField addTextField; @Override public void start(Stage primaryStage) { generalTableView = new TableView<>(); TableColumn<General, String> generalColumn = new TableColumn<>("Col"); generalColumn.setCellValueFactory(new PropertyValueFactory<>("col")); generalTableView.getColumns().add(generalColumn); Button loadDataButton = new Button("Load Data"); loadDataButton.setOnAction(event -> { createGeneralTable(); loadGeneralData(); dataSearch(); }); searchBox = new TextField(); searchBox.setPromptText("Search"); addTextField = new TextField(); addTextField.setPromptText("Add Data"); Button addButton = new Button("Add"); addButton.setOnAction(event -> addData(addTextField.getText())); HBox searchBoxContainer = new HBox(searchBox); HBox addBoxContainer = new HBox(addTextField, addButton); VBox root = new VBox(generalTableView, loadDataButton, searchBoxContainer, addBoxContainer); Scene scene = new Scene(root, 400, 400); primaryStage.setScene(scene); primaryStage.show(); loadDataButton.fire(); // Trigger the button action when the program starts } public static void main(String[] args) { launch(args); } static class General { private ObjectProperty<String> col; public General(String col) { this.col = new SimpleObjectProperty<>(col); } public String getCol() { return col.get(); } public void setCol(String col) { this.col.set(col); } public ObjectProperty<String> colProperty() { return col; } } static class OracleConnect { public static Connection getConnection() { Connection connection = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "system", "o4a75e"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return connection; } } private void createGeneralTable() { try { Connection connection = OracleConnect.getConnection(); String createTableGeneral = "CREATE TABLE general (col VARCHAR2(50))"; PreparedStatement statement = connection.prepareStatement(createTableGeneral); statement.execute(); statement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } private void loadGeneralData() { try { Connection connection = OracleConnect.getConnection(); String query = "SELECT col FROM general"; PreparedStatement statement = connection.prepareStatement(query); ResultSet resultSet = statement.executeQuery(); generalList = FXCollections.observableArrayList(); while (resultSet.next()) { String col = resultSet.getString("col"); General general = new General(col); generalList.add(general); } generalTableView.setItems(generalList); resultSet.close(); statement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } private void dataSearch() { ObservableList<General> generalList = FXCollections.observableArrayList(generalTableView.getItems()); FilteredList<General> filteredData = new FilteredList<>(generalList, b -> true); searchBox.textProperty().addListener((observable, oldValue, newValue) -> { filteredData.setPredicate(general -> { if (newValue.isEmpty() || newValue.isBlank() || newValue == null) { return true; } String searchKeyword = newValue.toLowerCase(); if (general.getCol().toLowerCase().contains(searchKeyword)) { return true; } else { return false; } }); }); SortedList<General> sortedData = new SortedList<>(filteredData); sortedData.comparatorProperty().bind(generalTableView.comparatorProperty()); generalTableView.setItems(sortedData); } private void addData(String data) { try { Connection connection = OracleConnect.getConnection(); String insertQuery ="INSERT INTO general (col) VALUES (?)"; PreparedStatement statement = connection.prepareStatement(insertQuery); statement.setString(1, data); statement.executeUpdate(); General general = new General(data); generalList.add(general); statement.close(); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } }
TableViewin the application and therefore, also the database, like theaddDatamethod in the example that is triggered if I press a button. I think the problem is that thedataSearchmethod is only invoked once and therefore theObservableListobject calledgeneralListwhich stands outside of the listener doesn't get updated whenTableViewis modified.TableView. The database is totally irrelevant to that.