Multiple independent stages in JavaFX -


is there way launch multiple independent stages in javafx? independent mean stages created main thread.

at moment application more or less algorithm plot charts , tables during execution (mainly check whether results correct/ debug).

the problem cannot figure out how create , show multiple stages independently, i.e. this

public static void main(){     double[] x = subfunction.dosomething();     plotutil.plot(x); //creates new window , shows chart/table etc.     double[] y = subfunction.dosomethingelse();     plotutil.plot(y); //creates new window , shows chart/table etc.     ..... } 

which allow use plotutil 1 use plotting functions in other scripting languages (like matlab or r).

so main question how "design" plotutils? far tried 2 things

  1. plotutils uses application.launch each plot call (creating new stage single scene every time) --> not work application.launch can invoked once.
  2. create kind of "main stage" during first call plotutils, reference created application , start subsequent stages there --> not work using application.launch(someclass.class) not able reference created application instance.

what kind structure/design allow me implement such plotutils function?

update 1:

i came following idea , wondering whether there major mistakes in solution.

interface implemented "plots"

public abstract class qpmapplication implements stagecreator {    @override    public abstract  stage createstage(); } 

plotting functionality:

public class plotstage {     public static boolean toolkitinialized = false;      public static void plotstage(string title, qpmapplication stagecreator) {         if (!toolkitinialized) {             thread appthread = new thread(new runnable() {                 @override                 public void run() {                     application.launch(initapp.class);                 }             });             appthread.start();         }          while (!toolkitinialized) {             try {                 thread.sleep(100);             } catch (interruptedexception e) {                 e.printstacktrace();             }         }         platform.runlater(new runnable() {             @override             public void run() {                 stage stage = stagecreator.createstage();                 stage.show();             }         });     }      public static class initapp extends application {         @override         public void start(final stage primarystage) {             toolkitinialized = true;         }     } } 

using it:

public class plotstagetest {      public static void main(string[] args) {          qpmapplication qpm1 = new qpmapplication() {             @override             public stage createstage() {                 stage stage = new stage();                 stackpane root = new stackpane();                 label label1 = new label("label1");                 root.getchildren().add(label1);                 scene scene = new scene(root, 300, 300);                 stage.settitle("first stage");                 stage.setscene(scene);                 return stage;             }         };          plotstage.plotstage(qpm1);          qpmapplication qpm2 = new qpmapplication() {             @override             public stage createstage() {                 stage stage = new stage();                 stackpane root = new stackpane();                 label label1 = new label("label2");                 root.getchildren().add(label1);                 scene scene = new scene(root, 300, 200);                 stage.settitle("second stage");                 stage.setscene(scene);                 return stage;             }         };          plotstage.plotstage(qpm2);          system.out.println("done");      } } 

the easiest approach here refactor application driven fx application thread. example, rewrite original code block as

public class main extends application {      @override     public void start(stage primarystageignored) {         double[] x = subfunction.dosomething();         plotutil.plot(x); //creates new window , shows chart/table etc.         double[] y = subfunction.dosomethingelse();         plotutil.plot(y); //creates new window , shows chart/table etc.         //  .....     }      public static void main(string[] args) {         launch(args);     } } 

now plotutil.plot(...) merely creates stage, puts scene in it, , show()s it.

this assumes methods you're calling don't block, if have wrap them in task , call plotutils.plot(...) in onsucceeded handler task.

if want drive non-javafx application, there's well-known hack force javafx application thread start if it's not started, creating new jfxpanel. jfxpanel should created on awt event dispatch thread.

here's basic example of second technique. start application , type "show" console. (type "exit" exit.)

import java.util.scanner; import java.util.concurrent.futuretask;  import javafx.application.platform; import javafx.embed.swing.jfxpanel; import javafx.scene.scene; import javafx.scene.control.button; import javafx.scene.layout.stackpane; import javafx.stage.stage;  import javax.swing.swingutilities;   public class main {      private jfxpanel jfxpanel ;      public void run() throws exception {         boolean done = false ;         try (scanner scanner = new scanner(system.in)) {             while (! done) {                 system.out.println("waiting command...");                 string command = scanner.nextline();                 system.out.println("got command: "+command);                 switch (command.tolowercase()) {                 case "exit":                      done = true;                     break ;                 case "show":                     showwindow();                     break;                 default:                     system.out.println("unknown command: commands \"show\" or \"exit\"");                    }             }             platform.exit();         }     }      private void showwindow() throws exception {         ensurefxapplicationthreadrunning();         platform.runlater(this::_showwindow);     }      private void _showwindow() {         stage stage = new stage();         button button = new button("ok");         button.setonaction(e -> stage.hide());         scene scene = new scene(new stackpane(button), 350, 75);         stage.setscene(scene);         stage.show();         stage.tofront();     }      private void ensurefxapplicationthreadrunning() throws exception {          if (jfxpanel != null) return ;          futuretask<jfxpanel> fxthreadstarter = new futuretask<>(() -> {             return new jfxpanel();         });         swingutilities.invokelater(fxthreadstarter);         jfxpanel = fxthreadstarter.get();     }      public static void main(string[] args) throws exception {         platform.setimplicitexit(false);         system.out.println("starting main....");         new main().run();     }  } 

here more along lines follow, if wanted user interact via os terminal (i.e. using system.in). uses first technique, application driven fx application subclass. here create 2 background threads, 1 read commands system.in, , 1 process them, passing them via blockingqueue. though nothing displayed in main fx application thread, still bad idea block thread waiting commands. while threading adds small level of complexity, avoids "jfxpanel" hack, , doesn't rely on there being awt implementation present.

import java.util.scanner; import java.util.concurrent.blockingqueue; import java.util.concurrent.callable; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import java.util.concurrent.linkedblockingqueue;  import javafx.application.application; import javafx.application.platform; import javafx.scene.scene; import javafx.scene.control.button; import javafx.scene.layout.stackpane; import javafx.stage.stage;   public class fxdriver extends application {      blockingqueue<string> commands ;     executorservice exec ;      @override     public void start(stage primarystage) throws exception {          exec = executors.newcachedthreadpool(runnable -> {             thread t = new thread(runnable);             t.setdaemon(true);             return t ;         });          commands = new linkedblockingqueue<>();          callable<void> commandreadthread = () -> {             try (scanner scanner = new scanner(system.in)) {                 while (true) {                     system.out.print("enter command: ");                     commands.put(scanner.nextline());                 }             }          };          callable<void> commandprocessingthread = () -> {             while (true) {                 processcommand(commands.take());             }         };          platform.setimplicitexit(false);         exec.submit(commandreadthread);         exec.submit(commandprocessingthread);     }      private void processcommand(string command) {         switch (command.tolowercase()) {         case "exit":              platform.exit();             break ;         case "show":             platform.runlater(this::showwindow);             break;         default:             system.out.println("unknown command: commands \"show\" or \"exit\"");            }     }      @override     public void stop() {         exec.shutdown();     }      private void showwindow() {         stage stage = new stage();         button button = new button("ok");         button.setonaction(e -> stage.hide());         scene scene = new scene(new stackpane(button), 350, 75);         stage.setscene(scene);         stage.show();         stage.tofront();     }      public static void main(string[] args) {         launch(args);     } } 

Comments

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -