在javaFX中运行swing应用程序

问题描述:

我有一个可以在Swing上完美运行的代码,但是我想将其集成到javaFX上. 我知道我必须使用SwingNode,但是该代码在javaFX中不起作用. 这是我使用的librarie的.jar: http://forge. scilab.org/index.php/p/jlatexmath/downloads/694/

I have a code that work perfectly on Swing but I want to integrate it on javaFX. I know that I must use SwingNode but the code dosen't work in javaFX. this is .jar of librarie I use : http://forge.scilab.org/index.php/p/jlatexmath/downloads/694/

这是swing的结果:

this is the result in swing :

这是Swing中的代码:

this is the code in Swing :

 import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import org.scilab.forge.jlatexmath.TeXIcon;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

public class LatexExample extends JFrame implements ActionListener {

    private JTextArea latexSource;
    private JButton btnRender;
    private JPanel drawingArea;

    public LatexExample() {
        this.setTitle("JLatexMath Example");
        this.setSize(500, 500);
        Container content = this.getContentPane();
        content.setLayout(new GridLayout(2, 1));
        this.latexSource = new JTextArea();

        JPanel editorArea = new JPanel();
        editorArea.setLayout(new BorderLayout());
        editorArea.add(new JScrollPane(this.latexSource),BorderLayout.CENTER);
        editorArea.add(btnRender = new JButton("Render"),BorderLayout.SOUTH);

        content.add(editorArea);
        content.add(this.drawingArea = new JPanel());
        this.btnRender.addActionListener(this);

        this.latexSource.setText("x=\\frac{-b \\pm \\sqrt {b^2-4ac}}{2a}");
    }

    public void render() {
        try {
            // get the text
            String latex = this.latexSource.getText();

            // create a formula
            TeXFormula formula = new TeXFormula(latex);

            // render the formla to an icon of the same size as the formula.
            TeXIcon icon = formula
                    .createTeXIcon(TeXConstants.STYLE_DISPLAY, 20);

            // insert a border
            icon.setInsets(new Insets(5, 5, 5, 5));

            // now create an actual image of the rendered equation
            BufferedImage image = new BufferedImage(icon.getIconWidth(),
                    icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = image.createGraphics();
            g2.setColor(Color.white);
            g2.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight());
            JLabel jl = new JLabel();
            jl.setForeground(new Color(0, 0, 0));
            icon.paintIcon(jl, g2, 0, 0);
            // at this point the image is created, you could also save it with ImageIO

            // now draw it to the screen
            Graphics g = drawingArea.getGraphics();
            g.drawImage(image,0,0,null);
        } catch (Exception ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
                    JOptionPane.INFORMATION_MESSAGE);
        }

    }

    public static void main(String[] args) {
        LatexExample frame = new LatexExample();
        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if( e.getSource()==this.btnRender ) {
            render();
        }

    }
}

这是JavaFX版本(不起作用,什么都没有出现):

and this is JavaFX version (dosen't work nothing appear) :

private void createAndSetSwingContent() {

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {

                    // get the text
                    String latex = "x=\\frac{-b \\pm \\sqrt {b^2-4ac}}{2a}";

                    // create a formula
                    TeXFormula formula = new TeXFormula(latex);

                    // render the formla to an icon of the same size as the formula.
                    TeXIcon icon = formula
                            .createTeXIcon(TeXConstants.STYLE_DISPLAY, 20);

                    // insert a border
                    icon.setInsets(new Insets(5, 5, 5, 5));

                    // now create an actual image of the rendered equation
                    final BufferedImage images = new BufferedImage(icon.getIconWidth(),
                            icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
                    Graphics2D g2 = images.createGraphics();
                    g2.setColor(Color.white);
                    g2.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight());
                    label.setForeground(new Color(0, 0, 0));
                    icon.paintIcon(label, g2, 0, 0);
                    // at this point the image is created, you could also save it with ImageIO


                    panel = new JPanel(){
                        @Override
                        protected void paintComponent(Graphics g)
                        {
                            Graphics2D g2d = (Graphics2D) g.create();
                            super.paintComponent(g);
                            g.drawImage(images, 0, 0, null);
                        }
                    };
                    swingNode.setContent(label);
                    swingNode.setContent(panel);


                } catch (Exception ex) {
                    ex.printStackTrace();
                    JOptionPane.showMessageDialog(null, ex.getMessage(), "Error",
                            JOptionPane.INFORMATION_MESSAGE);
                }
            }

        });
    }

您应该能够使用 FXGraphics2D 并完全消除了Swing.我修改了一个示例程序来产生此输出(这是一个小型JavaFX应用程序):

You ought to be able to render this output to a JavaFX Canvas using FXGraphics2D and eliminate Swing completely. I modified one of the sample programs to produce this output (it is a small JavaFX app):

不幸的是,直接将TeXIcon绘制到FXGraphics2D实例并不能提供很好的输出(很可能是由于TextLayout渲染中的问题,我还无法跟踪其来源),但是绘制到首先创建一个图像(如您在示例中所做的那样),然后将其绘制到JavaFX Canvas上似乎很好.

Unfortunately drawing the TeXIcon directly to the FXGraphics2D instance doesn't give nice output (most likely due to issues in the TextLayout rendering that I haven't been able to trace the source of yet), but drawing to an image first (as you did in your example) then drawing the image to the JavaFX Canvas seems to work fine.

/* =================
 * FXGraphics2DDemo3
 * =================
 * 
 * Copyright (c) 2014, Object Refinery Limited.
 * All rights reserved.
 *
 * http://www.jfree.org/fxgraphics2d/index.html
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   - Neither the name of the Object Refinery Limited nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL OBJECT REFINERY LIMITED BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

package org.jfree.fx.demo;

import static javafx.application.Application.launch;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javax.swing.JLabel;
import org.jfree.fx.FXGraphics2D;
import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import org.scilab.forge.jlatexmath.TeXIcon;

/**
 * http://*.com/questions/25027060/running-swing-application-in-javafx
 */
public class FXGraphics2DDemo3 extends Application {

    static class MyCanvas extends Canvas { 

        private FXGraphics2D g2;

        private TeXIcon icon;

        public MyCanvas() {
            this.g2 = new FXGraphics2D(getGraphicsContext2D());

            // create a formula
            TeXFormula formula = new TeXFormula("x=\\frac{-b \\pm \\sqrt {b^2-4ac}}{2a}");

            // render the formla to an icon of the same size as the formula.
            this.icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 20);

            // Redraw canvas when size changes. 
            widthProperty().addListener(evt -> draw()); 
            heightProperty().addListener(evt -> draw()); 
        }  

        private void draw() { 
            double width = getWidth(); 
            double height = getHeight();
            getGraphicsContext2D().clearRect(0, 0, width, height);

            // ideally it should be possible to draw directly to the FXGraphics2D
            // instance without creating an image first...but this does not generate
            // good output
            //this.icon.paintIcon(new JLabel(), g2, 50, 50);

            // now create an actual image of the rendered equation
            BufferedImage image = new BufferedImage(icon.getIconWidth(),
                    icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D gg = image.createGraphics();
            gg.setColor(Color.WHITE);
            gg.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight());
            JLabel jl = new JLabel();
            jl.setForeground(new Color(0, 0, 0));
            icon.paintIcon(jl, gg, 0, 0);
            // at this point the image is created, you could also save it with ImageIO

            this.g2.drawImage(image, 0, 0, null);
        } 

        @Override 
        public boolean isResizable() { 
            return true;
        }  

        @Override 
        public double prefWidth(double height) { return getWidth(); }  

        @Override 
        public double prefHeight(double width) { return getHeight(); } 
    } 


    @Override 
    public void start(Stage stage) throws Exception {
        MyCanvas canvas = new MyCanvas();
        StackPane stackPane = new StackPane(); 
        stackPane.getChildren().add(canvas);  
        // Bind canvas size to stack pane size. 
        canvas.widthProperty().bind( stackPane.widthProperty()); 
        canvas.heightProperty().bind( stackPane.heightProperty());  
        stage.setScene(new Scene(stackPane)); 
        stage.setTitle("FXGraphics2DDemo3.java"); 
        stage.setWidth(700);
        stage.setHeight(390);
        stage.show(); 

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

这是直接绘制方程式的程序的修订版(要进行此工作,必须预加载JLatexMath jar文件中包含的必需字体,以便JavaFX可以使用它们):

here is a revised version of the program that draws the equation directly (to make this work it is necessary to preload the required fonts that are included in the JLatexMath jar file so that JavaFX can use them):

/* =================
 * FXGraphics2DDemo3
 * =================
 * 
 * Copyright (c) 2014, Object Refinery Limited.
 * All rights reserved.
 *
 * http://www.jfree.org/fxgraphics2d/index.html
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   - Neither the name of the Object Refinery Limited nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL OBJECT REFINERY LIMITED BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */

package org.jfree.fx.demo;

import static javafx.application.Application.launch;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import org.jfree.fx.FXGraphics2D;

import org.scilab.forge.jlatexmath.Box;
import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import org.scilab.forge.jlatexmath.TeXIcon;

/**
 * http://*.com/questions/25027060/running-swing-application-in-javafx
 */
public class FXGraphics2DDemo3 extends Application {

    static class MyCanvas extends Canvas { 

        private FXGraphics2D g2;

        private Box box;

        public MyCanvas() {
            this.g2 = new FXGraphics2D(getGraphicsContext2D());
            this.g2.scale(20, 20);

            // create a formula
            TeXFormula formula = new TeXFormula("x=\\frac{-b \\pm \\sqrt {b^2-4ac}}{2a}");
            TeXIcon icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, 20);

            // the 'Box' seems to be the thing we can draw directly to Graphics2D
            this.box = icon.getBox();

            // Redraw canvas when size changes. 
            widthProperty().addListener(evt -> draw()); 
            heightProperty().addListener(evt -> draw()); 
        }  

        private void draw() { 
            double width = getWidth(); 
            double height = getHeight();
            getGraphicsContext2D().clearRect(0, 0, width, height);
            this.box.draw(g2, 1, 5);
        } 

        @Override 
        public boolean isResizable() { 
            return true;
        }  

        @Override 
        public double prefWidth(double height) { return getWidth(); }  

        @Override 
        public double prefHeight(double width) { return getHeight(); } 
    } 


    @Override 
    public void start(Stage stage) throws Exception {
        javafx.scene.text.Font.loadFont(FXGraphics2DDemo3.class.getResourceAsStream("/org/scilab/forge/jlatexmath/fonts/base/jlm_cmmi10.ttf"), 1);
        javafx.scene.text.Font.loadFont(FXGraphics2DDemo3.class.getResourceAsStream("/org/scilab/forge/jlatexmath/fonts/maths/jlm_cmsy10.ttf"), 1);
        javafx.scene.text.Font.loadFont(FXGraphics2DDemo3.class.getResourceAsStream("/org/scilab/forge/jlatexmath/fonts/latin/jlm_cmr10.ttf"), 1);
        MyCanvas canvas = new MyCanvas();
        StackPane stackPane = new StackPane(); 
        stackPane.getChildren().add(canvas);  
        // Bind canvas size to stack pane size. 
        canvas.widthProperty().bind( stackPane.widthProperty()); 
        canvas.heightProperty().bind( stackPane.heightProperty());  
        stage.setScene(new Scene(stackPane)); 
        stage.setTitle("FXGraphics2DDemo3.java"); 
        stage.setWidth(700);
        stage.setHeight(390);
        stage.show(); 

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}