javaswingbufferedimagejeditorpane

How To Take A BufferedImage From JEditorPane?


I need to load a URL into a JEditorPane, then take a BufferedImge from the JEditorPane, my code below will get me a blank/black image :

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.text.html.*;
import java.io.*;

public class Html_Browser
{
  public static void main(String[] args)
  {
    Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();
    JEditorPane editorPane=new JEditorPane();
    editorPane.setEditorKit(new HTMLEditorKit());
    editorPane.setEditable(false);

    try
    {
      editorPane.setPage("https://news.yahoo.com/");
      Thread.sleep(3000);
      BufferedImage saveimg=new BufferedImage((int)screenSize.getWidth(),(int)screenSize.getHeight()-36,BufferedImage.TYPE_INT_RGB);
      Graphics2D g2=saveimg.createGraphics();
      editorPane.paint(g2); 
      ImageIO.write(saveimg,"png",new File("test.png"));
    }
    catch (Exception e)
    {
      editorPane.setContentType("text/html");
      editorPane.setText("<html>Connection issues!</html>");
    }
    
    JFrame frame=new JFrame();
    frame.getContentPane().add(editorPane);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setBounds(0,0,(int)screenSize.getWidth(),(int)screenSize.getHeight()-36);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

I added a 3-second delay, but it didn't work, what's the right way to do it ?


Solution

  • You might be able to use this approach.

    It modifies the editor pane to read all the files synchronously. Then a PropertyChanngeEvent is generated when the I/O is finished.

    import java.awt.*;
    import java.awt.event.*;
    import java.beans.*;
    import java.io.*;
    import java.net.*;
    import javax.swing.*;
    import javax.swing.text.*;
    import javax.swing.text.html.*;
    import java.awt.image.*;
    
    public class EditorPaneLoadSynchronously extends JFrame
        implements ActionListener, PropertyChangeListener
    {
        private JEditorPane html;
        private JTextField webURL;
    
        public EditorPaneLoadSynchronously()
        {
            JPanel urlPanel = new JPanel();
            getContentPane().add(urlPanel, BorderLayout.NORTH);
    
            webURL = new JTextField("https://stackoverflow.com", 15);
            webURL.addActionListener(this);
            urlPanel.add(webURL);
    
            JButton gotoURL = new JButton("Goto URL");
            gotoURL.addActionListener(this);
            urlPanel.add(gotoURL);
    
            HTMLEditorKit editorKit = new HTMLEditorKit()
            {
                private final ViewFactory factory = new HTMLFactory()
                {
                    public View create(Element elem)
                    {
                        View v = super.create(elem);
    
                        if ((v != null) && (v instanceof ImageView))
                        {
                            ((ImageView)v).setLoadsSynchronously( true );
                        }
    
                        return v;
                    }
                };
    
                public ViewFactory getViewFactory()
                {
                    return factory;
                }
            };
    
            html = new JEditorPane();
    //      html.setEditorKit( editorKit );
    //      html.setEditable( false );
            html.addPropertyChangeListener("page", this);
    
            JScrollPane scrollPane = new JScrollPane(html);
            scrollPane.setPreferredSize( new Dimension(400, 400) );
            getContentPane().add(scrollPane);
        }
    
        public void actionPerformed(ActionEvent e)
        {
            try
            {
    //          html.setDocument( new HTMLDocument() );
                html.setPage( new URL(webURL.getText()) );
                System.out.println("After setPage");
            }
            catch(Exception exc)
            {
                System.out.println(exc);
            }
        }
    
        public void propertyChange(PropertyChangeEvent e)
        {
            try
            {
                System.out.println("Page Loaded");
    //          BufferedImage bi = ScreenImage.createImage(html);
    //          ScreenImage.writeImage(bi, "sync.jpg");
            }
            catch(Exception ee) {}
        }
    
        private static void createAndShowGUI()
        {
            EditorPaneLoadSynchronously frame = new EditorPaneLoadSynchronously();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationByPlatform( true );
            frame.setVisible( true );
    
            frame.actionPerformed(null);
        }
    
        public static void main(String[] args) throws Exception
        {
            java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
        }
    }
    

    Note: the above code uses the Screen Image convenience class. You can replace it with your only code to create and write the BufferedImage.