public class MedicalCenter {
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(() -> {
new Login().setVisible(true); <----------
new TimeAndDate().setVisible(true); <----------
});
}
}
Are these lines used just to start showing main windows of swing application?
new keyword is always used while creating objects
They do create objects but you didn't kept their reference.
So you cannot access those objects later on if you want to.
Currently teaching myself advanced object programming and I've hit a snag when trying to write a Javafx solution to a given Swing solution.
The problem was to develop an RMI program with Polling. I have the Swing version working perfectly, and I believe I've narrowed the problem down this section of code.
Swing
public static void main(String args[])
{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run()
{
new PollClient().setVisible(true);
}
});
}
JavaFx
public static void main(String args[])
{
Platform.runLater(new Runnable(){
#Override
public void run()
{
launch(args);
}
});
}
Any advice would be appreciated.
Platform.runLater specifies in its documentation that it executed on the JavaFX application thread at an unspecified time in the future. For this thread to exist you must first launch your application.
This means that since the application isnt launched the action to launch the application is never executed.
Regardless, JavaFX should be launched from within the main function, no need to insert a delay:
Application.launch(PollClient.class, args)
My application is Swing-based. I would like to introduce JavaFX and configure it to render a Scene on a secondary display.
I could use a JFrame to hold a JFXPanel which could hold a JFXPanel but I would like to achieve this with JavaFX API.
Subclassing com.sun.glass.ui.Application and using Application.launch(this) is not an option because the invoking thread would be blocked.
When instantiating a Stage from Swing EDT, the error I get is:
java.lang.IllegalStateException: Toolkit not initialized
Any pointers?
EDIT: Conclusions
Problem: Non-trivial Swing GUI application needs to run JavaFX components. Application's startup process initializes the GUI after starting up a dependent service layer.
Solutions
Subclass JavaFX Application class and run it in a separate thread e.g.:
public class JavaFXInitializer extends Application {
#Override
public void start(Stage stage) throws Exception {
// JavaFX should be initialized
someGlobalVar.setInitialized(true);
}
}
Sidenote: Because Application.launch() method takes a Class<? extends Application> as an argument, one has to use a global variable to signal JavaFX environment has been initialized.
Alternative approach: instantiate JFXPanel in Swing Event Dispatcher Thread:
final CountDownLatch latch = new CountDownLatch(1);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JFXPanel(); // initializes JavaFX environment
latch.countDown();
}
});
latch.await();
By using this approach the calling thread will wait until JavaFX environment is set up.
Pick any solution you see fit. I went with the second one because it doesn't need a global variable to signal the initialization of JavaFX environment and also doesn't waste a thread.
Found a solution. If I just create a JFXPanel from Swing EDT before invoking JavaFX Platform.runLater it works.
I don't know how reliable this solution is, I might choose JFXPanel and JFrame if turns out to be unstable.
public class BootJavaFX {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JFXPanel(); // this will prepare JavaFX toolkit and environment
Platform.runLater(new Runnable() {
#Override
public void run() {
StageBuilder.create()
.scene(SceneBuilder.create()
.width(320)
.height(240)
.root(LabelBuilder.create()
.font(Font.font("Arial", 54))
.text("JavaFX")
.build())
.build())
.onCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent windowEvent) {
System.exit(0);
}
})
.build()
.show();
}
});
}
});
}
}
Since JavaFX 9, you can run JavaFX application without extending Application class, by calling Platform.startup():
Platform.startup(() ->
{
// This block will be executed on JavaFX Thread
});
This method starts the JavaFX runtime.
The only way to work with JavaFX is to subclass Application or use JFXPanel, exactly because they prepare env and toolkit.
Blocking thread can be solved by using new Thread(...).
Although I suggest to use JFXPanel if you are using JavaFX in the same VM as Swing/AWT, you can find more details here: Is it OK to use AWT with JavaFx?
I checked the source code and this is to initialize it
com.sun.javafx.application.PlatformImpl.startup(()->{});
and to exit it
com.sun.javafx.application.PlatformImpl.exit();
I used following when creating unittests for testing javaFX tableview updates
public class testingTableView {
#BeforeClass
public static void initToolkit() throws InterruptedException
{
final CountDownLatch latch = new CountDownLatch(1);
SwingUtilities.invokeLater(() -> {
new JFXPanel(); // initializes JavaFX environment
latch.countDown();
});
if (!latch.await(5L, TimeUnit.SECONDS))
throw new ExceptionInInitializerError();
}
#Test
public void updateTableView() throws Exception {
TableView<yourclassDefiningEntries> yourTable = new TableView<>();
.... do your testing stuff
}
}
even though this post is not test related, then it helped me to get my unittest to work
without the BeforeClass initToolkit, then the instantiation of TableView in the unittest would yield a message of missing toolkit
There's also way to initialize toolkit explicitly, by calling:
com.sun.javafx.application.PlatformImpl#startup(Runnable)
Little bit hacky, due to using *Impl, but is useful, if you don't want to use Application or JXFPanel for some reason.
re-posting myself from this post
private static Thread thread;
public static void main(String[] args) {
Main main = new Main();
startup(main);
thread = new Thread(main);
thread.start();
}
public static void startup(Runnable r) {
com.sun.javafx.application.PlatformImpl.startup(r);
}
#Override
public void run() {
SoundPlayer.play("BelievexBelieve.mp3");
}
This is my solution. The class is named Main and implements Runnable. Method startup(Runnable r) is the key.
Using Jack Lin’s answer, I found that it fired off the run() twice. With a few modifications that also made the answer more concise, I offer the following;
import com.sun.javafx.application.PlatformImpl;
public class MyFxTest implements Runnable {
public static void main(String[] args) {
MyFxTest main = new MyFxTest();
PlatformImpl.startup((Runnable) main);
}
#Override
public void run() {
// do your testing;
System.out.println("Here 'tis");
System.exit(0); // Optional
}
}
I'm on Windows using NetBeans IDE and lanterna. I try to create a SwingTerminal, but it won't show.
public static void main(String[] args) throws Exception {
SwingTerminal t = TerminalFacade.createSwingTerminal();
while (true) {
Thread.sleep(100);
}
}
I also tried displaying the JFrame, but I get null from SwingTerminal.getJFrame().
t.getJFrame().setVisible(true);
I also tried running the program from the command-line, thinking it might be an issue with NetBeans, but it didn't work either (cygwin). How can I make the SwingTerminal show?
I should've look at the Google Discussions first. Hacked together from a bunch of snippets:
public static void main(String[] args) {
// Create a Terminal and Screen.
SwingTerminal terminal = new SwingTerminal();
Screen screen = new Screen(terminal);
screen.startScreen();
// Add listener(s) for the Window. The JFrame won't shut
// down itself when Alt+F4 or the like is pressed or the
// Window is closed by pressing the X button.
terminal.getJFrame().addWindowListener(
new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
screen.stopScreen();
}
}
);
}
I have being implementing a client in Java as application with Swing. But now I want to build also Applet from it. What is the best way to redesign/refactor in order to be able to build both of them easily and keeping it DRY.
This is a short extraction of code which has main()
public class Client {
public static final ScheduledExecutorService SERVICE;
protected static String host;
protected static int port;
static {
SERVICE = Executors.newSingleThreadScheduledExecutor();
host =
port =
}
public static void main(String[] args) {
//initalize netty
//create user interface = JFrame in SwingUtilities.invokeLater
connect();
}
public static void connect () {
//connect using netty
}
So I copy this file as a separate one, extend it from JApplet and change main to init, so it can be run, but of course it is ugly, because much of code is just copy-pasted.
Is there universal solution how to redesign it?
UPD:
public class Client {
public static void main (String[] args) {
App app = new App();
app.connect();
}
}
public class Applet extends JApplet {
public void init () {
App app = new App();
app.connect();
}
}
and to move all initialization logic to App
Remove the bulk of the application to group of classes that do not rely on the top level container.
This means, you can reuse/redeploy the application as you need without chaining your self to a top level container.
You will then need a "main" class for your desktop entry point and a "applet" class. This would simply construct the applications main interface and attach it to a screen container.
This is one of the reasons why we suggest you never override from a top level container directly, but extend your application logic/UI from simple container, like JPanel