I have a class caled ItemGUI which is handling everything related with the user interface. The user, is able to add some links, which are the items, so when he inserts a link an
You can use a Timer to schedule a repeating task.
Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially
Something along the lines of this code should do the trick.
Timer timer = new Timer();
TimerTask task = new TimerTask(){
public void run() {
getPrice(); //your task
}
};
timer.schedule(task, 0, 5000); //first is delay, second is repeat period
...
// on button click, simple cancel the task
task.cancel()
Update
The clearest solution by MadProgrammer's suggestion is to use swing Timers, like this:
protected javax.swing.Timer refresherTimer = null;
protected void stopRefreshing() {
if (refresherTimer != null) {
refresherTimer.stop();
refresherTimer = null;
}
}
protected void startRefreshing() {
stopRefreshing();
refresherTimer = new Timer(500, e -> {
newItem.getPrice()
});
refresherTimer.start();
}
public void onStartButtonClicked() {
Item newItem = new Item(newItemField.getText());
// here newItem should be added to a list of items which should be in the ItemGUI class
startRefreshing();
}
public void onStopButtonClicked() {
stopRefreshing();
}
Original answer
It would be nice to have some utility named e.g. GuiTimer
which would make your task as easy as:
protected GuiThread.Task refresherTask = null;
protected void cancelRefreshing() {
if (refresherTask != null) {
refresherTask.cancel();
refresherTask = null;
}
}
public void onStartButtonClicked() {
Item newItem = new Item(newItemField.getText());
// should also be added to a list of items which should be in the ItemGUI class
cancelRefreshing();
refresherTask = GuiThread.scheduleAtFixedRate(() -> {
newItem.getPrice()
}, 0, 5, TimeUnit.SECONDS);
}
public void onStopButtonClicked() {
cancelRefreshing();
}
The problem with regular timers is that they invoke the callback function on their own thread, not on the gui thread, so it requires the developer to ensure proper threading. Unfortunately the builtin java EventQueue does not support dispatching delayed tasks.
For this reason I like to have the following utility called GuiTimer
, which will act as a pure gui-threaded timer:
public class GuiTimer {
public static final ScheduledThreadPoolExecutor executor =
new ScheduledThreadPoolExecutor(1);
public static interface Task {
public void cancel();
}
private static class CancelStateTask implements Task {
public volatile boolean canceled = false;
@Override
public void cancel() {
this.canceled = true;
}
}
public static Task schedule(final Runnable action) {
CancelStateTask task = new CancelStateTask();
EventQueue.invokeLater(() -> {
if (!task.canceled)
action.run();
});
return task;
}
public static Task schedule(final Runnable command, long delay,
TimeUnit unit) {
ScheduledFuture<?> future = executor.schedule(
() -> EventQueue.invokeLater(command), delay, unit);
return () -> future.cancel(false);
}
public static Task scheduleAtFixedRate(Runnable command,
long initialDelay, long period, TimeUnit unit) {
ScheduledFuture<?> future = executor.scheduleAtFixedRate(
() -> EventQueue.invokeLater(command), initialDelay,
period, unit);
return () -> future.cancel(false);
}
public static Task scheduleWithFixedDelay(Runnable command,
long initialDelay, long delay, TimeUnit unit) {
ScheduledFuture<?> future = executor.scheduleAtFixedRate(
() -> EventQueue.invokeLater(command), initialDelay, delay,
unit);
return () -> future.cancel(false);
}
public static void shutdown() {
executor.shutdown();
}
}
First off, I'm in no way sure how this should be done, but I think I have a suggestion for how you could make it work. In a project I'm working on at the moment I use ExecutorService to handle my thread pool. I have to mention here, that I started working with threads in Java a little over a week ago myself, so I apologize if what I'm suggestion is too basic or wrong.
My suggestion is, that you could create a static boolean variable that you could use for controlling your loop. Code could look something like this:
public static boolean isRunning;
public static void main(String[] args) {
ExecutorService executerService = Executors.newCachedThreadPool();
executerService.execute(new Runnable() {
@Override
public void run() {
isRunning=true;
while (isRunning){
System.out.println("hello world"); //Your loop here
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Whenever you set the isRunning boolean to false the loop will stop, and the Thread will finish after a little while.
As for observer-observable classes I don't know this and I'm not sure I understand your last question.