在 Swing 应用中使用的 JavaFX HTML 编辑器,重新加载编辑器无法正常工作。

huangapple go评论73阅读模式
英文:

JavaFX HTML editor in swing application and reloading editor not working

问题

The provided text appears to be a code-related discussion about integrating JavaFX HTML editors into a Swing-based application. The code is quite extensive, but based on your request, I will only provide translations for the comments and text portions. Here they are:

Calling program:

// calling program
public WebViewTest a1=null;

if(a1 == null){
    a1 = new WebViewTest();
    a1.initAndShowGUI("Starting 2", 900,900);
}
else{
    a1.initAndShowGUI("Starting 2 restart", 900,900);
    // when I used the following I got an error with .setContent
    //a1.setVisible();
    //a1.setContent("Selected Call 2");
}

Editor program:

// does not work
public void setContent(String content){
    htmlEditor.setHtmlText(content);
}

Please note that this code appears to be a part of a larger Java application, and its functionality relies on a specific context. If you have any questions or need further assistance with this code, feel free to ask.

英文:

I have a large Java swing-based application and needed to add a text editor. The JavaFX HTML editor appears to be my best option. I am hoping to have the HTML Editor in a JPanel aside other controls in the Swing environment. I can do this but I must not be closing the JavaFX HTML Editor correctly because I can only get the HTML Editor to run once unless I exit the entire larger program. The first time I open the Editor app the Platform.runLater() executes. The second call to the Editor app does not run the Platform.runLater(). I have included code for the "calling" program with 2 buttons. Each button calls the Editor code. The first button click opens the editor correctly. Clicking a second time opens the Swing window but the HTML Editor is not loaded. The second code is for the program that opens a Swing frame and tries to load the JavaFX HTML Editor into a JPanel in the JFrame. This is on a Windows machine and NetBeans is my IDE. Thanks for any help you can offer.

Doug

calling program
package testjavafxeditorswingcaller;

import testhtmleditorminimal.TestHTMLeditorMinimal;

/**
 *
 * @author DStockman
 */
public class NewJFrame extends javax.swing.JFrame {

    /**
     * Creates new form NewJFrame
     */
    public NewJFrame() {
        initComponents();
    }
    
    

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        call1PB = new javax.swing.JButton();
        call2PB = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        call1PB.setText("Call1");
        call1PB.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                call1PBActionPerformed(evt);
            }
        });

        call2PB.setText("Call2");
        call2PB.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                call2PBActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(163, 163, 163)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(call2PB)
                    .addComponent(call1PB))
                .addContainerGap(165, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(57, 57, 57)
                .addComponent(call1PB)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(call2PB)
                .addContainerGap(193, Short.MAX_VALUE))
        );

        setSize(new java.awt.Dimension(416, 308));
        setLocationRelativeTo(null);
    }// </editor-fold>                        

    private void call1PBActionPerformed(java.awt.event.ActionEvent evt) {                                        
        TestHTMLeditorMinimal a1 = new TestHTMLeditorMinimal();
        a1.main(null);
        a1.setVisible(true);
    }                                       

    private void call2PBActionPerformed(java.awt.event.ActionEvent evt) {                                        
        TestHTMLeditorMinimal a2 = new TestHTMLeditorMinimal();
        a2.main(null);
        a2.setVisible(true);
    }                                       

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new NewJFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JButton call1PB;
    private javax.swing.JButton call2PB;
    // End of variables declaration                   
}
Editor program
package testhtmleditorminimal;

import java.awt.BorderLayout;
import java.awt.Dimension;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.event.ActionEvent;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ToolBar;
import javafx.scene.web.HTMLEditor;
import javafx.scene.web.WebView;
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 *
 * @author DStockman
 */
public class TestHTMLeditorMinimal extends JApplet {

    private static final int JFXPANEL_WIDTH_INT = 1200;
    private static final int JFXPANEL_HEIGHT_INT = 1000;
    private static JFXPanel fxContainer;
    public static HTMLEditor htmlEditor=null;
    public static Scene scene = null;
    public static JFrame frame=null;
    public static JApplet applet=null;
    public static JPanel jpanel=null;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                } catch (Exception e) {
                }
                
                frame = new JFrame("JavaFX 2 in Swing");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                applet = new TestHTMLeditorMinimal();
                applet.init();
                frame.setContentPane(applet.getContentPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                applet.start();
            }
        });
    }
    
    @Override
    public void init() {
        jpanel = new JPanel();
        fxContainer = new JFXPanel();
        fxContainer.setPreferredSize(new Dimension(JFXPANEL_WIDTH_INT, JFXPANEL_HEIGHT_INT));
        jpanel.add(fxContainer);
        add(jpanel, BorderLayout.CENTER);
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                createScene();
            }
        });

    }
    
    private void createScene() {
        htmlEditor = new HTMLEditor();
        htmlEditor.setHtmlText("Testing");
        addToolBar();
        scene = new Scene(htmlEditor);
        fxContainer.setScene(scene);
    } // ********************************************
    
    
    public void addToolBar(){
        Node toolNode = htmlEditor.lookup(".top-toolbar");
        Node webNode = htmlEditor.lookup(".web-view");

        if (toolNode instanceof ToolBar && webNode instanceof WebView) {
            ToolBar bar = (ToolBar) toolNode;
            WebView webView = (WebView) webNode;
            //engine = webView.getEngine();
            Button btnCaretExit = new Button("Close");
            bar.getItems().addAll(btnCaretExit);
            
// I tried multiple ways to exit program
            btnCaretExit.setOnAction((ActionEvent event) -> {
                Platform.setImplicitExit(true);
                applet.destroy();
                fxContainer.removeAll();
                Platform.exit();
                frame.dispose();
            });
        }
    }
  
}

Thanks for the suggestions! I got rid of the JApplet. I continued to test various ways to close the code with the HTMLEditor in it but the HTMLEditor would still not reinitialize when a second start of the code was attempted (without shutting down the calling program). The only way I could get the program to work was your suggestion of: frame.setVisible(false); I tried a couple different methods to re-open the hidden app. What I am doing right now from the calling program is:

    // calling program
    public WebViewTest a1=null;
    
    if(a1 == null){
        a1 = new WebViewTest();
        a1.initAndShowGUI("Starting 2", 900,900);
    }
    else{
    	a1.initAndShowGUI("Starting 2 restart", 900,900);
    	// when I used the following I got an error with .setContent
    	//a1.setVisible();
    	//a1.setContent("Selected Call 2");
    }

// in the editor program
// does not work
public void setContent(String content){
	htmlEditor.setHtmlText(content);
}

Is the above method going to keep creating new (quasi)instances of the code every time it is opened because of the repeated calls to initAndShowGUI? Sorry for my ignorance on the basics of Java functioning.

Thanks again!
Doug

答案1

得分: 1

根据您的要求,以下是翻译好的部分:

Empirically, absent a reason to destroy the applet or shut down the JavaFX runtime, I focused on the "Close" button's action handler method in your example to effect the desired behavior. The precise formulation will depend on your use case.

You could alter the frame's visibility, reusing it as needed:
您可以更改窗口的可见性,根据需要重用它:

btnCaretExit.setOnAction((ActionEvent event) -> {
    frame.setVisible(false);
});

You could alter the frame's default closing operation and tell it to close, reusing it as needed:
您可以更改窗口的默认关闭操作,并告诉它关闭,根据需要重用它:

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

btnCaretExit.setOnAction((ActionEvent event) -> {
    frame.setVisible(false);
    frame.dispatchEvent(newWindowEvent(
        frame, WindowEvent.WINDOW_CLOSING));
});

You could open the HTMLEditor in a modal dialog as shown below in a variation of this example. Instead of a Button, a WindowListener observes the dialog's closing to access the editor's content. As JApplet is deprecated, you may want to migrate by using an intermediate hybrid similar to your example and those seen here:

您可以像下面这样在模态对话框中打开HTMLEditor,这是这个示例的一个变体。不使用按钮,WindowListener观察对话框的关闭以访问编辑器的内容。由于JApplet已被弃用,您可能希望通过使用类似于您的示例以及在此处看到的中间混合来迁移:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.HTMLEditor;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;

public class SwingEditorTest {

    private HTMLEditor editor;

    private void initAndShowGUI() {
        // This method is invoked on the EDT thread
        var frame = new JFrame("Swing and JavaFX");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final var fxPanel = new JFXPanel() {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(600, 300);
            }
        };
        Platform.runLater(() -> {
            editor = initFX(fxPanel);
        });
        var dialog = new JDialog(frame);
        dialog.add(fxPanel);
        dialog.pack();
        dialog.setLocationRelativeTo(frame);
        dialog.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Platform.runLater(() -> {
                    System.out.println(editor.getHtmlText());
                });
            }
        });
        frame.add(new JButton(new AbstractAction("Edit") {
            @Override
            public void actionPerformed(ActionEvent e) {
                dialog.setVisible(true);
            }
        }), BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private HTMLEditor initFX(JFXPanel fxPanel) {
        // This method is invoked on the JavaFX thread
        StackPane root = new StackPane();
        Scene scene = new Scene(root);
        editor = new HTMLEditor();
        editor.setHtmlText("Testing");
        root.getChildren().add(editor);
        fxPanel.setScene(scene);
        return editor;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new SwingEditorTest()::initAndShowGUI);
    }
}

请注意,这些代码示例中的注释和说明并未翻译。

英文:

Empirically, absent a reason to destroy the applet or shut down the JavaFX runtime, I focused on the <kbd>Close</kbd> button's action handler method in your example to effect the desired behavior. The precise formulation will depend on your use case.

You could alter the frame's visibility, reusing it as needed:

btnCaretExit.setOnAction((ActionEvent event) -&gt; {
frame.setVisible(false);
});

You could alter the frame's default closing operation and tell it to close, reusing it as needed:

frame.setDefaultCloseOperation(
JFrame.DO_NOTHING_ON_CLOSE);
…
btnCaretExit.setOnAction((ActionEvent event) -&gt; {
frame.setVisible(false);
frame.dispatchEvent(newWindowEvent(
frame, WindowEvent.WINDOW_CLOSING));
});

在 Swing 应用中使用的 JavaFX HTML 编辑器,重新加载编辑器无法正常工作。

You could open the HTMLEditor in a modal dialog as shown below in a variation of this example. Instead of a Button, a WindowListener observes the dialog's closing to access the editor's content. As JApplet is deprecated, you may want to migrate by using an intermediate hybrid similar to your example and those seen here:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.HTMLEditor;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
/**
* @see https://stackoverflow.com/q/76550530/230513
* @see https://stackoverflow.com/a/31576647/230513
*/
public class SwingEditorTest {
private HTMLEditor editor;
private void initAndShowGUI() {
// This method is invoked on the EDT thread
var frame = new JFrame(&quot;Swing and JavaFX&quot;);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final var fxPanel = new JFXPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 300);
}
};
Platform.runLater(() -&gt; {
editor = initFX(fxPanel);
});
var dialog = new JDialog(frame);
dialog.add(fxPanel);
dialog.pack();
dialog.setLocationRelativeTo(frame);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Platform.runLater(() -&gt; {
System.out.println(editor.getHtmlText());
});
}
});
frame.add(new JButton(new AbstractAction(&quot;Edit&quot;) {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(true);
}
}), BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private HTMLEditor initFX(JFXPanel fxPanel) {
// This method is invoked on the JavaFX thread
StackPane root = new StackPane();
Scene scene = new Scene(root);
editor = new HTMLEditor();
editor.setHtmlText(&quot;Testing&quot;);
root.getChildren().add(editor);
fxPanel.setScene(scene);
return editor;
}
public static void main(String[] args) {
EventQueue.invokeLater(new SwingEditorTest()::initAndShowGUI);
}
}

在 Swing 应用中使用的 JavaFX HTML 编辑器,重新加载编辑器无法正常工作。

huangapple
  • 本文由 发表于 2023年6月25日 21:00:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76550530.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定