Nickool Nickool - 3 months ago 9x
Java Question

timer action performs only after the thread is finished

enter image description hereI have a swing GUI named SpyBiteDemo, it will call another class(Parser) and do some calculations and show some data in a jtable inside this GUI(SpyBiteDemo). I have a jbutton1 and I want to when click on it to show my timer to begin like 1,2,3,4,5,....seconds

what happens is my timer is running correctly however it does not show value unless it is done with all the program that is filling the jtable which means the action it is detecting is I perform the action after jtable appears.

I am a complete newbie on Java for event listeners and I have searched timer, timer task, schedule, everything and could not understand what's wrong.I also tried while(true) and did not fix it.I also tried duration of 1000,0,everything no affects.

I tried to use action command,sleeping the thread, it did not is what I did:

public class SpyBiteDemo extends javax.swing.JFrame {

* Creates new form SpyBiteDemo
private long startTime;
Timer timer = new Timer(0, new TimerListener());

private class TimerListener implements ActionListener {

public void actionPerformed(ActionEvent aEvt) {

long time = (System.currentTimeMillis() - startTime) / 1000;
label3.setText(time + " seconds");


private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
startTime = evt.getWhen();
String SeedUrl = jTextField1.getText();
Parser P = new Parser(this);

it will start showing label3 value only after it is filling the jtable on my jframe.I want the timer to start from when I am clicking the button.

with trashgod's links I had come up with this example which is comepletely runnable on your machine, this works perfect except that when I the program finishes, it does not stop the timer since I don't know where to do it, I know I should do it in addPropertyChangeListener, however I do not have timer value.

* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
package javaapplication7;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

* @see
public class DisplayLog {

private static final String NAME = "C:\\wamp\\bin\\mysql\\mysql5.6.17\\bin\\scosche.sql";

private static class LogWorker extends SwingWorker<TableModel, String> {

private final File file;
private final DefaultTableModel model;

private LogWorker(File file, DefaultTableModel model) {
this.file = file;
this.model = model;
model.setColumnIdentifiers(new Object[]{file.getAbsolutePath()});

protected TableModel doInBackground() throws Exception {
BufferedReader br = new BufferedReader(new FileReader(file));
String s;
while ((s = br.readLine()) != null) {
return model;

protected void process(List<String> chunks) {
for (String s : chunks) {
model.addRow(new Object[]{s});

protected void done() {}


private void display() {
JFrame f = new JFrame("DisplayLog");
JLabel m=new JLabel("time");
JButton jb=new JButton("run");
f.add(m, BorderLayout.SOUTH);
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
JProgressBar jpb = new JProgressBar();
f.add(jpb, BorderLayout.NORTH);
f.add(new JScrollPane(table));
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
LogWorker lw = new LogWorker(new File(NAME), model);
lw.addPropertyChangeListener((PropertyChangeEvent ev) -> {
SwingWorker.StateValue s = (SwingWorker.StateValue) ev.getNewValue();
int timeDelay = 0;
ActionListener time;
time = new ActionListener() {
public void actionPerformed(ActionEvent e) {
m.setText(System.currentTimeMillis() / 1000 + "seconds");


Timer timer=new Timer(timeDelay, time);
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new DisplayLog().display();


It looks like the rows that comprise your table come from the network with variable, indeterminate latency. As shown here, you can load data into your TableModel in the background of a SwingWorker. As shown here, you can calculate intermediate progress in a way that makes sense for your application and display it in a PropertyChangeListener.