javaFX : How to periodically load information from db and show it on a Label?

694 views Asked by At

I want to execute a method periodically, this method get informations from database it show it into a label, I tried the following code :

 Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
             @Override
             public void run() {
                 //update information
                 miseAjour();
             }
            }, 0, 2000);

when i run the main program, the background service run also normaly but when the informations changes on db i get this exception:

Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0

And this is the code of method miseAjour :

public void miseAjour(){
    try {

        dbConnection db = new dbConnection();
        Connection connect = db.connectiondb();
        connect.setAutoCommit(false);
        Statement stmt= connect.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent  FROM  gss_aderent ");  
        int nbrAderent = rs.getInt("nbrAderent"); 
        rs.close();
        stmt.close();
        connect.commit();
        connect.close();
        main_nbrAdrTot.setText(nbrAderent + "");
    } catch (SQLException ex) {
        Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
    }
   }
2

There are 2 answers

0
KacemSys On BEST ANSWER

Finnaly i resolved the problem ,here is the code :

public class TimerServiceApp {
    public void start() throws Exception {
        TimerService service = new TimerService();
        service.setPeriod(Duration.seconds(10));
        service.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent t) {
                main_nbrAdrTot.setText(t.getSource().getMessage());
            }
        });
        service.start();
    }



    private class TimerService extends ScheduledService<Integer> {
        private final StringProperty  nbrTotAderent = new SimpleStringProperty();


         public final void  setTotalAderentNumber(String value ) {
             nbrTotAderent.set(value);
         }


        public String getTotalAderentNumber() throws SQLException  {
        String nbrAderent = null;
        ResultSet rs=null;
        Statement stmt=null;
        Connection connect=null;

        try {
        dbConnection db = new dbConnection();
        connect = db.connectiondb();
        connect.setAutoCommit(false);
        stmt= connect.createStatement();
        rs = stmt.executeQuery("SELECT count(*) as nbrAderent  FROM  gss_aderent ");  
        nbrAderent = String.valueOf(rs.getInt("nbrAderent")); 
        connect.commit();
        } catch (SQLException ex) {
        Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
        }
        finally {
        rs.close();
        stmt.close();
        connect.close();
        }
        System.out.println(" Total aderent number updated to :" + nbrAderent + " Aderents ");
        return nbrAderent;
        }

        protected Task<Integer> createTask() {
            return new Task<Integer>() {
                protected Integer call() throws SQLException {

                    nbrTotAderent.setValue(getTotalAderentNumber());
                    updateMessage(getTotalAderentNumber());
                    return  Integer.parseInt(getTotalAderentNumber());
                }
            };
        }
    }
} `

and i called this service by :

 TimerServiceApp s = new TimerServiceApp();
        s.start();

i dont know if the solution is optimised but it work :) thank you @ItachiUchiha i took the solution from yout answer in the following link

5
ItachiUchiha On

You can Timer for this, but I would recommend to use the JavaFX provided API called as ScheduledService.

ScheduledService is made to execute the same Task at regular intervals and since it creates a Task internally, there are API which help you to bind the value to the UI controls.

ScheduledService<Object> service = new ScheduledService<Object>() {
     protected Task<Object> createTask() {
         return new Task<Object>() {
             protected Object call() {
                 // Call the method and update the message
                 updateMessage(miseAjour());
                 return object; // Useful in case you want to return data, else null
             }
         };
     }
 };
 service.setPeriod(Duration.seconds(10)); //Runs every 10 seconds

 //bind the service message properties to your Label
 label.textProperty().bind(service.messageProperty()); // or use your label -> main_nbrAdrTot

Inside the dbcall method miseAjour, return the value that you have fetched and you want to update the label with :

public String miseAjour(){
    String nbrAderent = null;
    try {
        dbConnection db = new dbConnection();
        Connection connect = db.connectiondb();
        connect.setAutoCommit(false);
        Statement stmt= connect.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT count(*) as nbrAderent  FROM  gss_aderent ");  
        nbrAderent = String.valueOf(rs.getInt("nbrAderent")); 
        connect.commit();
    } catch (SQLException ex) {
        Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
    }
    finally {
        rs.close();
        stmt.close();
        connect.close();
    }
    return nbrAderent;
}