Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX 8 swing compatibility

I am currently evaluating whether it would be feasible to convert my current Swing Application to JavaFX 8 using SwingNode and then slowly change everything to JavaFX components. I have stumbled over two problems, which may be lingering bugs in JavaFX 8, but I can't be sure.

  1. After adding content to the SwingNode the Javafx menu isn't painted properly (most of the time), resulting in a black bar
  2. Making JScrollBars non-opaque doesn't seem to work

    import java.awt.Color;
    import java.awt.GridLayout;
    
    import javafx.application.Application;
    import javafx.embed.swing.SwingNode;
    import javafx.scene.Scene;
    import javafx.scene.control.Menu;
    import javafx.scene.control.MenuBar;
    import javafx.scene.layout.StackPane;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    
    
    public class Test extends Application {    
    
        @Override
        public void start(Stage stage) throws Exception {
            stage.setMaximized(true);
    
            VBox vbox = new VBox();
            MenuBar menuBar = new MenuBar();
            menuBar.getMenus().add(new Menu("bla"));
            vbox.getChildren().add(menuBar);
    
            StackPane mainPane = new StackPane();        
            mainPane.setPrefSize(9999, 9999); //Better way to ensure all space used?
            vbox.getChildren().add(mainPane);
            vbox.setVisible(true);
    
            Scene scene = new Scene(vbox, 9999, 9999); //Better way to ensure all space used?
            stage.setScene(scene);
    
            SwingNode swingNode = new SwingNode();
            mainPane.getChildren().add(swingNode);
    
            JPanel jPanel = new JPanel();
            swingNode.setContent(jPanel); //Seems to interfere with painting of menu
    
            jPanel.setBackground(Color.WHITE);
            jPanel.setLayout(new GridLayout(2, 1));
            jPanel.add(new JPanel());
    
            JPanel nonOpaquePanel = new JPanel();
            nonOpaquePanel.setOpaque(false);
            JScrollPane scrollPane = new JScrollPane(nonOpaquePanel);
            scrollPane.setOpaque(false);
            scrollPane.getViewport().setOpaque(false); //Black background -> Bug?
            jPanel.add(scrollPane);
    
            stage.show();
        }
    
        /**
         * Main method launching the application.
         */
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    Executable jar

Edit: I edited my example to use the EDT for creating the Swing components. That didn't change anything. Or am I doing something wrong?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;


public class Test extends Application {
    private JPanel jPanel = null;

    @Override
    public void start(Stage stage) throws Exception {
        if (Platform.isFxApplicationThread()) { // all of this happens on the fx application thread
            stage.setMaximized(true);

            VBox vbox = new VBox();
            MenuBar menuBar = new MenuBar();
            menuBar.getMenus().add(new Menu("bla"));
            vbox.getChildren().add(menuBar);

            StackPane mainPane = new StackPane();        
            mainPane.setPrefSize(9999, 9999); //Better way to ensure all space used?
            vbox.getChildren().add(mainPane);
            vbox.setVisible(true);

            Scene scene = new Scene(vbox, 9999, 9999); //Better way to ensure all space used?
            stage.setScene(scene);

            SwingNode swingNode = new SwingNode();
            mainPane.getChildren().add(swingNode);                    

            SwingUtilities.invokeLater(new Runnable() { //Use EDT to build swing components              
                @Override
                public void run() {
                    jPanel = new JPanel();

                    jPanel.setBackground(Color.WHITE);
                    jPanel.setLayout(new GridLayout(2, 1));
                    jPanel.add(new JPanel());

                    JLabel nonOpaquePanel = new JLabel("Bla");
                    nonOpaquePanel.setPreferredSize(new Dimension(5000, 5000));
                    nonOpaquePanel.setOpaque(false);
                    JScrollPane scrollPane = new JScrollPane(nonOpaquePanel);
                    scrollPane.setOpaque(false);
                    scrollPane.getViewport().setOpaque(false); //Black background -> Bug?
                    jPanel.add(scrollPane);
                }
            });

            Thread.sleep(1000); //terrible way to wait for the EDT, I know
            swingNode.setContent(jPanel); //Seems to interfere with painting of menu            
            stage.show();

            SwingUtilities.invokeLater(new Runnable() { //I am pretty sure this isn't necessary, but whatever                       
                @Override
                public void run() {
                    jPanel.repaint();    
                }
            });
        }
    }

    /**
     * Main method launching the application.
     */
    public static void main(String[] args) {
        launch(args);
    }
}
like image 958
Teferus Avatar asked Apr 02 '14 10:04

Teferus


People also ask

Is JavaFX compatible with Swing?

JavaFX SDK provides the JFXPanel class, which is located in the javafx. embed. swing package and enables you to embed JavaFX content into Swing applications.

Which version of Java contains Swing JavaFX?

Originally distributed as a separately downloadable library, Swing has been included as part of the Java Standard Edition since release 1.2. The Swing classes and components are contained in the javax.

Will JavaFX replace Swing?

Is JavaFX replacing Swing as the new client UI library for Java SE? Yes. However, Swing will remain part of the Java SE specification for the foreseeable future, and therefore included in the JRE.

Does Java 8 include JavaFX?

JavaFX for Oracle Java 8 is not a separate installation. JavaFX is included in Oracle JDK 8 running on OS X, Linux x86 and Windows.

What is JavaFX (Java Swing)?

JavaFX even contains a WebView supported by the popular WebKit browser; therefore, you’ll be able to introduce websites or net applications within JavaFX. What is Swing? Swing API may be a set of extendable GUI parts to ease the developer’s life to form JAVA primarily based Front End/GUI Applications.

How to run JavaFX applications from behind a firewall?

As of version 7.2, the NetBeans IDE provides support for Swing applications with the embedded JavaFX content. When creating a new project, in the JavaFX category choose JavaFX in Swing Application. To run this application from behind a firewall, you must specify proxy settings in order for the application to access a remote resource.

Can swing and JavaFX coexist in the same application?

With JavaFX and Swing data coexisting in a single application, you may encounter the following interoperability situations: A JavaFX data change is triggered by a change in Swing data. A Swing data change is triggered by a change in JavaFX data. Changing JavaFX Data in Response to a Change in Swing Data.

Are there any incompatibilities between Java SE 8 and Java 7?

"Incompatibilities between JDK 8 and JDK 7" "Features Removed from Java SE 8" "Features Removed from JDK 8" "Deprecated APIs" The following compatibility documents track incompatibility between adjacent Java versions. For example, this compatibility page reports only Java SE 8 incompatibilities with Java SE 7, and not with previous versions.


3 Answers

Try wrapping your update code in this when you make an update call. This code has helped me before on other projects.

Platform.runLater(new Runnable() {
            @Override
            public void run() {
                // Update the text node with calculated results
            }
       });

Source

like image 143
Kyte Avatar answered Nov 19 '22 02:11

Kyte


You can use -Djavafx.embed.singleThread=true, so you dont have to make the event dispatching on your own.

JavaFx APIDesign

like image 39
Dashy Avatar answered Nov 19 '22 02:11

Dashy


Must have been a bug in JavaFX, this very example is working fine now.

like image 33
Teferus Avatar answered Nov 19 '22 04:11

Teferus