JavaFX8 swing兼容性

JavaFX8 swing兼容性,java,javafx,javafx-8,Java,Javafx,Javafx 8,我目前正在评估是否可以使用SwingNode将我当前的Swing应用程序转换为JavaFX8,然后慢慢地将所有内容更改为JavaFX组件。我遇到了两个问题,这可能是JavaFX8中的遗留错误,但我不能确定 将内容添加到SwingNode后,不会绘制Javafx菜单 正确(大多数情况下),导致出现黑条 使JScrollBars非不透明似乎不起作用 import java.awt.Color; import java.awt.GridLayout; import javafx.applicatio

我目前正在评估是否可以使用SwingNode将我当前的Swing应用程序转换为JavaFX8,然后慢慢地将所有内容更改为JavaFX组件。我遇到了两个问题,这可能是JavaFX8中的遗留错误,但我不能确定

  • 将内容添加到SwingNode后,不会绘制Javafx菜单 正确(大多数情况下),导致出现黑条
  • 使JScrollBars非不透明似乎不起作用

    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);
        }
    }
    

  • 编辑: 我编辑了我的示例以使用EDT创建Swing组件。这没有改变任何事情。还是我做错了什么

    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);
        }
    }
    

    当您进行更新调用时,请尝试将更新代码包装在此中。这段代码以前在其他项目上帮助过我

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

    您可以使用
    -Djavafx.embed.singleThread=true
    ,这样您就不必自己进行事件调度


    一定是JavaFX中的一个bug,这个例子现在运行良好。

    我在JavaFX bug报告RT-36285中询问了这个问题,听到:"... 请检查代码中的线程。您在stackoverflow上提供的示例在JavaFX用户线程上调用Swing API。这对Swing和FX都不好。Swing API只能在EDT上调用,而FX API只能在JavaFX用户线程上调用。请先修复线程,看看它是如何改变的。如果仍然存在任何问题,请提交新的bug。“。您不会将
    JScrollBar
    s设置为非不透明,而是将整个
    JScrollPane
    设置为非不透明。然而,两者都不起作用。现在还不太清楚使用非不透明的
    JScrollBar
    s的
    JScrollPane
    会产生什么样的行为,但它很可能不会以这种方式工作(原则上)。当我将您的代码与进行比较时,您似乎需要将
    swingNode.setContent(…)
    调用到
    SwingUtilities.invokeLater中(…)
    而不是创建Swing内容本身。再加上@Dashy的单线程系统属性,你应该给它最好的效果。但目前你的代码在我看来是错误的。因为这是Java8
    Platform.runLater(()->…)
    可以使用。嗯……据我所知,这只适用于MacOS?在Windows上运行非常完美,在我当前的项目中进行了测试。