JavaFX not on FX application thread - java

So I've been given an assignment to make my application check for customers every x seconds through multithreading with Runnable. So I jammed ScheduledExecutorService into my controller class, and the new thread gets called and that's all dandy, but whenever I try making an Alert I get an IllegalStateException.
The class:
public class Line implements Runnable
{
public Line()
{
System.out.println("I'm made");
}
#Override
public void run()
{
System.out.println("I've started");
try
{
Alert alert = new Alert(AlertType.ERROR, "Line is empty");
alert.setTitle("Error");
alert.setHeaderText("Line empty");
System.out.println("I've ended");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
I've tried putting the whole run() function into Platform.runLater thing like so:
Platform.runLater(new Runnable() {
#Override
public void run()
{
System.out.println("I've started");
try
{
Alert alert = new Alert(AlertType.ERROR, "Line is empty");
alert.setTitle("Error");
alert.setHeaderText("Line empty");
System.out.println("I've ended");
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
But then Runnable complains there's no run().
Anyone got any idea how to do this? The code has to be called every x seconds through ScheduledExecutorService, and the alert must be made within the run() function.

You got yourself confused among two different Runnables. Your Line implements Runnable and thus have to implement run which would be executed by scheduler. But given that you want to relay UI work back to FX thread you need to pass it another Runnable implementation, a la:
public class Line implements Runnable
{
public Line()
{
System.out.println("I'm made");
}
#Override
public void run()
{
Platform.runLater(new Runnable() {
#Override
public void run()
{
System.out.println("I've started");
try
{
Alert alert = new Alert(AlertType.ERROR, "Line is empty");
alert.setTitle("Error");
alert.setHeaderText("Line empty");
System.out.println("I've ended");
} catch (Exception e) {
e.printStackTrace();
}
}});
}
}

Related

Java: How will I be able to create a Stop JButton which will stop the Runnable() thread?

I have created a simple HTTP server in Java by using a ServerSocket that accepts browser requests. The server is working fine without any errors. I have created a JForm using Swing that contains buttons to start and stop the server. In the start button I have added an ActionListener that runs my ServerMain class.
btnStartServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
try {
new Thread(new Runnable() {
public void run() {
ServerMain.main(new String[0]);
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}});
How will I be able to create a Stop JButton which will stop the Runnable() thread?
Run the server in the context of a class that implements the cancel() method of Future<V>. SwingWorker<T,V> is such a RunnableFuture<V>; a complete example is seen here.
You don't want to just kill a thread (by using Thread.stop()). The reasons why are listed in this article.
I assume the code in ServerMain.main(String... args) runs some kind of while(condition) loop, like this:
public class ServerMain{
public static boolean condition = true;
public static void main(String... args){
while(condition){
//do stuff
}
//close sockets and other streams.
//Call Thread.interupt() on all sleeping threads
}
}
Your button should set this condition to false somehow:
stopButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
try {
new Thread() {
public void run() {
// set condition to false;
ServerMain.condition = false;
}
}.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});

Infinite-while or for loop after ActionEvent not working in swing. why?

public void myMethod()
{
if (capture.isOpened()) {
while (true) { //This is The main issue.
capture.read(webcam_image);
if (!webcam_image.empty()) {
webcam_image = my_panel.detect(webcam_image);
temp = my_panel.matToBufferedImage(webcam_image);
my_panel.setimage(temp);
my_panel.repaint();
System.out.print("."); // It should prints "." but the above code doesn't works.
} else {
System.out.println(" --(!) No captured frame -- Break!");
break;
}
}
}
}
This is invoking code of the above method...
actually it's an ActionEvent which can be fire on menu is clicked.
if (e.getActionCommand().equals("goLive")) {
System.out.println("Live...");
myMethod();
}
I know actually it's problem of the infinite while loop but here I need to put this condition at any cost.
The exact solution for this type of problem is Timer class. We can overcome this issue using the following code.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
myMethod();
}
}, 0);
Thanks google, oracle and java doc
Assuming that myMethod is called by an event listener (actionPerformed), the infinite loop is blocking the event dispatch thread.
You can avoid this by using SwingWorker or executing your loop on another thread:
public void myMethod()
{
if (capture.isOpened()) {
new Thread(new Runnable() { //Create a new thread and pass a Runnable with your while loop to it
#Override public void run() {
while (true) {
capture.read(webcam_image);
if (!webcam_image.empty()) {
webcam_image = my_panel.detect(webcam_image);
temp = my_panel.matToBufferedImage(webcam_image);
SwingUtilities.invokeLater(new Runnable() { //The following lines affect the GUI and must be executed on the event dispatch thread, so they should be wrapped inside a Runnable
#Override public void run() {
my_panel.setimage(temp);
my_panel.repaint();
}
}
try{
Thread.sleep(xxx); //consider waiting for a moment (e.g. 16ms)
} catch(InterruptedException e) { ... }
System.out.print(".");
} else {
System.out.println(" --(!) No captured frame -- Break!");
break;
}
}
}
}).start(); //Let the thread loop in the background
}
}

Java - get errors propagated from background thread

I am trying to run a background service as part of my GUI application. I am using an ExecutorService and I am getting a Future back from it. This code shows what I am doing:
play.addActionListener( new ActionListener() {
service.submit(new Runnable(){ .... } }
}
Now, the submission is happening on the GUI thread, which should propagate exceptions to the main thread. Now, I don't want to block the main thread on future.get, but I would rather have some way of checking for the result of the future, so that the exceptions are proapagated to the main thread. Any ideas?
You could use a listener pattern to be notified when the background thread is done. SwingWorker for instance allows for PropertyChangeListeners to listen to the SwingWorker.State state property and you could either do this or roll your own. This is one of my favorite features of a SwingWorker.
An example....
final MySwingWorker mySwingWorker = new MySwingWorker(webPageText);
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (pcEvt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
try {
mySwingWorker.get();
} catch (InterruptedException e) {
e.printStackTrace(); // this needs to be improved
} catch (ExecutionException e) {
e.printStackTrace(); // this needs to be improved
}
}
}
});
mySwingWorker.execute();
You can check Future.isDone() to see if it has finished, or you can have the background task perform the action e.g.
play.addActionListener( new ActionListener() {
service.submit(new Runnable(){
public void run() {
try {
// ....
} catch(Exception e) {
SwingUtils.invokeLater(new Runnable() {
public void run() {
handleException(e);
}
}
}
}
});
You could have an additional thread just to monitor the state of the future:
final Future<?> future = service.submit(...);
new Thread(new Runnable() {
public void run() {
try {
future.get();
} catch (ExecutionException e) {
runOnFutureException(e.getCause());
}
}
}).start();
And somewhere else:
public void runOnFutureException(Exception e) {
System.out.println("future returned an exception");
}

Starting background service in new thread freezes main application

I'm using a button to start a background service in my app. This is the code I'm using:
#Override
public void actionPerformed(ActionEvent action) {
if (action.getActionCommand().equals("Start")) {
while (true) {
new Thread(new Runnable() {
public void run() {
System.out.println("Started");
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
This does update the service every second, which it what I want. Problem is it freezes the rest of the application. How do I implement it so that that doesn't happen?
The following is likely to cause your application to pause:
while (true) {
...
}
Try removing those lines.
Edit: as per comment, to make the newly-launched thread fire every second, move the sleep and while loop inside the run() method:
if (action.getActionCommand().equals("Start")) {
new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("Started"); }
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
You're calling this method in the Thread that updates the GUI, and this you're pausing the GUI refresh. Spawn a new thread and execute that there.
an infinite loop ??
while (true) {.....}
how you supposed to get out of here -
add an print statement inside loop and you will come to know that you have been stuck here after button click
Ok I got it. Here's what I should have done:
#Override
public void actionPerformed(ActionEvent action) {
if (action.getActionCommand().equals("Start")) {
new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("Started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}

JBoss OrderedExecutor + CountDownLatch don't work as I expect?

Playing with OrderedExecutor, I tried using the CountDownLatch to start all the submitted tasks at the same time, but the tasks don't start, they're frozen.
Am i missing something?
import org.jboss.threads.OrderedExecutor;
final CountDownLatch taskUnfreezer = new CountDownLatch(1);
OrderedExecutor orderedExec = new OrderedExecutor(JBossExecutors.directExecutor(),10,JBossExecutors.directExecutor()) ;
orderedExec.executeNonBlocking(
new Runnable() {
#Override
public void run() {
try {
taskUnfreezer.await();
System.out.println("Task 1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
orderedExec.executeNonBlocking(
new Runnable() {
#Override
public void run() {
try {
taskUnfreezer.await();
System.out.println("Task 2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// Try to start all tasks
taskUnfreezer.countDown();
You are using JBossExecutors.directExecutor(). This executor does not execute things in a separate thread, but instead executes tasks in the thread that calls execute (this is useful for testing).
Your code block on the first call to orderedExec.executeNonBlocking, since that is calling taskUnfreezer.await() in the same thread, and you will never get to taskUnfreezer.countDown()

Categories

Resources