【问题标题】:JavaFX + AWT CanvasJavaFX + AWT 画布
【发布时间】:2016-12-16 05:24:25
【问题描述】:

我读到使用 JavaFX 运行 AWT 是个坏主意。 但是我们有一个在 Swing 上运行并使用 AWT 画布的旧应用程序(由于使用画布的外部库而无法更改)

真的有这么可怕的想法吗? 有解决办法吗?

【问题讨论】:

    标签: javafx awt


    【解决方案1】:

    更新

    虽然此答案中的代码过去可以在具有早期版本 JavaFX 的 Windows 上工作,但我在 OS X 10.9.5 + JavaFX 8u72 上重新测试了相同的代码,代码不再工作

    指示 JavaFX 线程在 awt 线程上等待初始化 awt 画布的行 swingNode.setContent(awtInitializerTask.get()); 永远不会返回,从而阻止应用程序的执行和启动。


    只需将您的 AWT 画布放在 SwingNode 中并观察您的线程管理,您就会没事的。

    import javafx.application.Application;
    import javafx.embed.swing.SwingNode;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    import javax.swing.*;
    import java.awt.*;
    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    
    public class AwtCanvasWrapper extends Application {
        private static final int W = 200;
        private static final int H = 100;
    
        @Override public void start(final Stage stage) throws Exception {
            final AwtInitializerTask awtInitializerTask = new AwtInitializerTask(() -> {
                JPanel jPanel = new JPanel();
                jPanel.add(new CustomAwtCanvas(W, H));
    
                return jPanel;
            });
    
            SwingUtilities.invokeLater(awtInitializerTask);
    
            SwingNode swingNode = new SwingNode();
            swingNode.setContent(awtInitializerTask.get());
    
            stage.setScene(new Scene(new Group(swingNode), W, H));
            stage.setResizable(false);
            stage.show();
        }
    
        private class AwtInitializerTask extends FutureTask<JPanel> {
            public AwtInitializerTask(Callable<JPanel> callable) {
                super(callable);
            }
        }
    
        private class CustomAwtCanvas extends Canvas {
            public CustomAwtCanvas(int width, int height) {
                setSize(width, height);
            }
    
            public void paint(Graphics g) {
                Graphics2D g2;
                g2 = (Graphics2D) g;
                g2.setColor(Color.GRAY);
                g2.fillRect(
                    0, 0, 
                    (int) getSize().getWidth(), (int) getSize().getHeight()
                );
                g2.setColor(Color.BLACK);
                g2.drawString("It is a custom canvas area", 25, 50);
            }
        }
    
        public static void main(String[] args) {
            Application.launch(args);
        }
    }
    

    这是输出:

    相关问题

    回答一些其他问题

    但那是用于摆动组件的。

    可以,但是 awt 组件可以封装在 Swing 组件中。

    此外它在文档中说它不应该用于重量级组件

    无论如何,它似乎对我有用,你的里程可能会有所不同。

    性能对我的应用至关重要

    然后在您的应用中尝试该方法并检查:

    1. 这幅画是可靠的。
    2. 性能可以接受。

    如果上述任何一项检查失败,那么您可能需要使用不同的方法(尽管我不知道该方法是什么,也许只是将 Frame 生成为一个新窗口,其中包含 AWT 画布内容而不是将画布嵌入到 JavaFX 场景中)。

    【讨论】:

    • 但是那个是用于swing组件的,而且它在文档中说它不应该用于重量级组件,画布是最重量级的组件之一,性能对我来说至关重要应用程序。
    • 根据评论更新了答案。我还要求,如果您想对答案提出异议,那很好,但如果您这样做,请尝试包含您失败尝试的代码或以更好的方法发布答案(即,请不要将责任放在回答者证明他们的答案是正确的,而不是做你的工作来证明答案是错误的)。
    • 是的,此答案中的代码不再有效,可能是由于自创建答案以来 JavaFX 中的一些实现更改。我已经更新了答案以说明这一点。
    猜你喜欢
    • 2015-04-14
    • 2011-04-23
    • 1970-01-01
    • 2012-04-23
    • 2015-04-15
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    相关资源
    最近更新 更多