I am working on an application that measures 'distance' driven by a Car object. Each Car is it's own thread, has a randomly generated speed, and I calculate the distance each car has driven. While I am able to get the correct data to print to the console from within the thread at whatever time interval I want (currently once/second but may update that later), I am trying to figure out a way to instead display that info in a swing GUI (either as a table row, or just as a textarea row) Since the Car class is a separate file, I can't have it push to the GUI directly (or at least, I don't know how to do that). There are 2 'columns' of info I need to update periodically: current speed, and distance.
What I tried doing: set a jtable and pull the row data: this allowed me to capture a snapshot but not to constantly update the data.
Pushing infor to a jtextarea: I can do that as a snapshot. When I tried wrapping it in a while loop (while thread running, append...) the system crashed. Same result when I tried wrapping the append in a Thread.sleep.
Since at any given time I can take a snapshot of the Car location (car.getLocation()), what I am thinking is that perhaps the main method can actively seek that snapshot every second, however, when I tried that with a while loop and a Thread.sleep, as mentioned, it crashed the system.
Also of note is that when complete, the GUI will allow for the creation of any number of Car objects, and I will want a row for each of them that will be updated periodically, so the distance numbers can be compared.
edit: based on the suggestion of @matt, I added a swing timer and modified the GUI to accommodate. The challenge now is that the new jtextfield only pops up on the display when I resize the page. Is there a way to also somehow update/refresh the GUI?
updated GUI element:
JButton carb = new JButton("add car");
GridBagConstraints carC = new GridBagConstraints();
carC.gridx = 1;
carC.gridy = 2;
carb.addActionListener(a -> {
totalCars++;
String carName = "Car" + totalCars;
Car car = new Car(carName);
cars.add(car);
Thread thread = new Thread(car);
JTextField t = new JTextField(50);
GridBagConstraints tC = new GridBagConstraints();
t.setEditable(false);
tC.gridx = 1;
tC.gridy = currentcol;
currentcol++;
content.add(t, tC);
running = true;
thread.start();
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
t.setText(df.format(car.getLocation()));
t.setText("Name: " + carName + ", Drive speed: " + car.getSpeed() + ", Current speed: "
+ car.getCurrentSpeed() + ", Location (distance from beginning): "
+ df.format(car.getLocation()));
}
};
Timer timer = new Timer(1000, taskPerformer);
timer.start();
});
content.add(carb, carC);
The code (so far): Car class:
private void setLocation(long timeElapsed) {
location = location + ((timeElapsed-lastCheck)*(currentSpeed*0.44704));
lastCheck = timeElapsed;
}
public void run() {
long startTime = System.currentTimeMillis();
long elapsedTime;
while (flag) {
try {
Thread.sleep(1000);
elapsedTime = System.currentTimeMillis()-startTime;
elapsedTime = elapsedTime/1000;
setLocation(elapsedTime);
System.out.println(getName()+": " + df.format(getLocation()) + " meters");
} catch (InterruptedException e) {
}
}
}
Here is how I tried using Thread.sleep from the main method. This didn't work (crashed the system):
while (running) {
try {
Thread.sleep(1000);
carArea.append("\nName: " + carName + ", Drive speed: " + car.getSpeed() + ", Current speed: "
+ car.getCurrentSpeed() + ", Location (distance from beginning): " + car.getLocation());
} catch (InterruptedException e) {
}
}