在javaFX中运行swing应用程序

在javaFX中运行swing应用程序,java,swing,javafx-2,javafx-8,Java,Swing,Javafx 2,Javafx 8,我有一个可以在Swing上完美工作的代码,但我想在javaFX上集成它。 我知道我必须使用SwingNode,但代码在javaFX中不起作用。 这是我使用的.jar图书馆: 这是swing的结果: 这是Swing中的代码: import org.scilab.forge.jlatexmath.TeXConstants; import org.scilab.forge.jlatexmath.TeXFormula; import org.scilab.forge.jlatexmath.TeXIc

我有一个可以在Swing上完美工作的代码,但我想在javaFX上集成它。 我知道我必须使用SwingNode,但代码在javaFX中不起作用。 这是我使用的.jar图书馆:

这是swing的结果:

这是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版本(dosen't work nothing Display):


您应该能够使用并完全消除Swing将此输出呈现到JavaFX画布。我修改了一个示例程序以生成此输出(它是一个小型JavaFX应用程序):

不幸的是,将
TeXIcon
直接绘制到
FXGraphics2D
实例并不能提供很好的输出(很可能是由于TextLayout呈现中的问题,我还无法跟踪问题的来源),而是先绘制到图像(就像您在示例中所做的那样)然后,将图像绘制到JavaFX画布似乎可以正常工作

/* =================
 * 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://stackoverflow.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可以使用它们):


如果您不介意将其光栅化为特定的大小,可以使用
javafx.embed.swing
中的
SwingFXUtils.toFXImage
静态方法:

    TeXFormula tex = new TeXFormula("a + b \\cdot x");
    java.awt.Image awtImage = tex.createBufferedImage(TeXConstants.STYLE_TEXT, 12, java.awt.Color.BLACK, null);
    Image fxImage = SwingFXUtils.toFXImage((BufferedImage) awtImage, null);
    ImageView view = new ImageView(fxImage);

fxImage
实例也可以传递给标记为.setGraphic的
方法,以便在某些控件(例如按钮)中使用。

现在,在 .
除了github页面上提出的一些小问题外,它工作得很好。该项目似乎并不活跃,但通过重新实现
LateXMathSkin
类,这些问题很容易解决。希望这能省去一些麻烦

下一个版本的JavaFX支持MathML:

  • JavaFX8更新192包含在Java8更新192中
  • javafx11
只需使用WebView控件和MathML并使用以下设置HTML内容:

<math display="block"> 
   <mrow> 
      <mi>x</mi> 
      <mo>=</mo> 
      <mfrac> 
         <mrow> 
            <mo>−</mo> 
            <mi>b </mi> 
            <mo>±</mo> 
            <msqrt> 
               <mrow> 
                  <msup> 
                     <mi>b</mi> 
                     <mn>2</mn> 
                  </msup> 
                  <mo>−</mo> 
                  <mn>4</mn> 
                  <mi>a</mi> 
                  <mi>c</mi> 
               </mrow> 
            </msqrt> 
         </mrow> 
         <mrow> 
            <mn>2</mn> 
            <mi>a</mi> 
         </mrow> 
      </mfrac> 
   </mrow>
</math>

x
= 
− 
B
± 
B
2.
− 
4.
A.
C
2.
A.

按照链接访问这些版本的早期访问。

super.paintComponent
作为第一个。代码行在受保护的void paintComponent(Graphics g)`内将减少可能的绘制延迟覆盖
getPreferredSize
inside
panel=new JPanel(){
请在将代码转储到我们之前清理您的代码(可疑的f.i.在不使用它的情况下创建graphics2d,将swingnode的内容设置两次…)谢谢你的建议。对于@kleopatra,我很理解第一条评论,但最后一条我不太理解。因为你接受了David的回答,我的隐含假设(与tex图书馆无关的问题)结果证明是错误的-所以我的第二条评论现在是无用的并且被删除了:-)对于所画的图片,如果方程太长,我可以在javafx Scrollpane中添加画布。这个解决方案最终是最适合我的用例的。图像似乎正确地调整了公式的大小,边缘只有很少的空白(这在大多数情况下都是完美的)。这在我的情况下也起了作用。我计划在几个应用程序中使用它,所以我将它放在一个方法中。谢谢!+1
    TeXFormula tex = new TeXFormula("a + b \\cdot x");
    java.awt.Image awtImage = tex.createBufferedImage(TeXConstants.STYLE_TEXT, 12, java.awt.Color.BLACK, null);
    Image fxImage = SwingFXUtils.toFXImage((BufferedImage) awtImage, null);
    ImageView view = new ImageView(fxImage);
<math display="block"> 
   <mrow> 
      <mi>x</mi> 
      <mo>=</mo> 
      <mfrac> 
         <mrow> 
            <mo>−</mo> 
            <mi>b </mi> 
            <mo>±</mo> 
            <msqrt> 
               <mrow> 
                  <msup> 
                     <mi>b</mi> 
                     <mn>2</mn> 
                  </msup> 
                  <mo>−</mo> 
                  <mn>4</mn> 
                  <mi>a</mi> 
                  <mi>c</mi> 
               </mrow> 
            </msqrt> 
         </mrow> 
         <mrow> 
            <mn>2</mn> 
            <mi>a</mi> 
         </mrow> 
      </mfrac> 
   </mrow>
</math>