Catching an event when a form SUBMIT button has been clicked on a JTextPane

Set a custom HTMLEditorKit on your JTextPane. In the example below, this is MyHTMLEditorKit. It contains a factory that is responsible for returning a custom FormView. In MyFormView, you can override the method submitData that is called when the submit button is pressed. The form data is passed to this method in a escaped form.

Main.java:

import javax.swing.text.html.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.awt.*;
import java.io.*;
 
public class Main extends JFrame
{
   final JTextField urlTextField = new JTextField();
   final JEditorPane htmlPane = new JEditorPane();
   JButton urlButton = new JButton("Go!");
 
   public Main() {
      htmlPane.setEditable(false);
      urlTextField.setText("file:c:\test.html");
 
      urlButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            loadPage(urlTextField.getText());
         }
      });
 
      htmlPane.setEditorKit(new MyHTMLEditorKit());
 
      getContentPane().setLayout(new BorderLayout());
      JPanel topPanel = new JPanel(new BorderLayout());
      topPanel.add(BorderLayout.CENTER, urlTextField);
      topPanel.add(BorderLayout.EAST, urlButton);
 
      getContentPane().add(BorderLayout.NORTH, topPanel);
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(htmlPane));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
 
      setSize(400, 400);
   }
 
   public void loadPage(String url) {
      try {
         htmlPane.setPage(new URL(urlTextField.getText()));
      }
      catch(Exception e) {
         System.out.println(e);
      }
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
   }
}

MyHTMLEditorKit.java:

import javax.swing.text.html.*;
import javax.swing.text.*;
 
public class MyHTMLEditorKit extends HTMLEditorKit {
   private static final ViewFactory customFactory = new MyHTMLFactory();
 
   public ViewFactory getViewFactory() {
      return customFactory;
   }
 
   public static class MyHTMLFactory extends HTMLEditorKit.HTMLFactory
   {
      public View create(Element elem) {
         Object o = elem.getAttributes().getAttribute(StyleConstants.NameAttribute);
 
         if (o instanceof HTML.Tag) {
            HTML.Tag kind = (HTML.Tag) o;
            if (kind == HTML.Tag.INPUT || kind == HTML.Tag.SELECT || kind == HTML.Tag.TEXTAREA) {
               return new MyFormView(elem);
            }
            else return super.create(elem);
         }
 
         return super.create(elem);
      }
   }
}

MyFormView.java:

import javax.swing.text.html.*;
import javax.swing.text.*;
import java.awt.event.*;
import java.util.*;
 
public class MyFormView extends FormView
{
   public MyFormView(Element elem) {
      super(elem);
   }
 
   public void actionPerformed(ActionEvent event) {
      super.actionPerformed(event);
   }
 
   public void submitData(String data) {
      System.out.println("Escaped data: " + data);
   }
}

A simple HTML file to test it with: test.html:

<html>
<body>
 
<form METHOD=POST ACTION="performyourownaction">
 
   <i>Subcategory:</i><br>
   <SELECT NAME="subcat">
      <OPTION> J2SE </OPTION>
      <OPTION> J2EE </OPTION>
      <OPTION> J2ME </OPTION>
      <OPTION> Other </OPTION>
   </SELECT>
   <p>
   <i>Subject:</i><br>
      <input type=text size=80 maxsize=200 name="subject"><p>
   <i>Question:</i><br>
      <textarea name="question" cols=60 rows=4></textarea><p>
 
   <br><br>
 
   <input TYPE=SUBMIT VALUE=" Submit Question! ">
</form>
 
</body>
</html>

Using SWT JFace TreeViewer

Create a ContentProvider for the TreeViewer: implement the methods in ITreeContentProvider. The following example shows you how to do this. The business objects are Category and Link. (For an extension of this code, check the Q&A How do I use a Sash?

Category.java:

import java.util.*;
 
public class Category {
   private String name;
   private Category parent;
   private ArrayList categories = new ArrayList();
   private ArrayList links = new ArrayList();
   
   public Category(String name, Category parent) {
      this.name = name;
      this.parent = parent;
   }
   
   public void addSubCategory(Category category) {
      categories.add(category);
   }
   
   public void addLink(Link link) {
      links.add(link);
   }
   
   public ArrayList getSubCategories() {
      return categories;
   }
   
   public ArrayList getLinks() {
      return links;
   }
   
   public boolean hasSubCategories() {
      return categories.size() > 0;
   }
   
   public boolean hasLinks() {
      return links.size() > 0;
   }
   
   public String getName() {
      return name;
   }
   
   public Category getParent() {
      return parent;
   }
   
   public String toString() {
      return name;
   }
}

Link.java:

public class Link {
   private String url;
   
   public Link(String url) {
      this.url = url;
   }
   
   public String getUrl() {
      return url;
   }
   
   public String toString() {
      return url;
   }
}

CategoryTreeContentProvider.java:

import org.eclipse.jface.viewers.*;
import java.util.*;
 
public class CategoryTreeContentProvider implements ITreeContentProvider 
{
   public Object[] getChildren(Object element) {
      Category category = (Category) element;
      System.out.println(category.getName());
      
      ArrayList children = new ArrayList();
      children.addAll(category.getSubCategories());
      children.addAll(category.getLinks());
            
      if (children.size() == 0) {
         return new Object[0];
      }
      
      return children.toArray();
   }
   
   public Object[] getElements(Object element) {
      return getChildren(element);
   }
   
   public boolean hasChildren(Object element) {
      if (element instanceof Category) {
         Category category = (Category) element;
      
         return category.hasSubCategories() || category.hasLinks();
      }
      
      return false;
   }
   
   public Object getParent(Object element) {
      if (element instanceof Category) {
         return ((Category) element).getParent();
      }
      
      return null;
   }
   
   public void dispose() {
      
   }
   
   public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
      
   }
}

Main.java:

import org.eclipse.jface.viewers.*;
import org.eclipse.jface.window.*;
import org.eclipse.swt.widgets.*;
 
public class Main extends ApplicationWindow 
{
   private Category rootCategory;
   
   public Main() {
      super(null);
      
      // statically create categories
      rootCategory = new Category("Java", null);
      Category j2seCategory = new Category("J2SE", rootCategory);
      Link link = new Link("http://java.sun.com/j2se/");
      j2seCategory.addLink(link);
      Category j2eeCategory = new Category("J2EE", rootCategory);
      link = new Link("http://java.sun.com/j2se/");
      j2eeCategory.addLink(link);
      Category j2meCategory = new Category("J2ME", rootCategory);
      link = new Link("http://java.sun.com/j2se/");
      j2meCategory.addLink(link);
      
      rootCategory.addSubCategory(j2seCategory);
      rootCategory.addSubCategory(j2eeCategory);
      rootCategory.addSubCategory(j2meCategory);
   }
   
   protected Control createContents(Composite parent) {
      TreeViewer treeViewer = new TreeViewer(parent);
      treeViewer.setContentProvider(new CategoryTreeContentProvider());
      treeViewer.setInput(rootCategory);
      
      return treeViewer.getTree();
   }
   
   public static void main(String []args) {
      Main main = new Main();
      main.setBlockOnOpen(true);
      main.open();
      
      Display.getCurrent().dispose();
   }
}

The contents that is displayed in the tree using the toString() method in Category and Link. This is not a clean separation of model and view. Instead, you can use a LabelProvider, a helper class with a callback method getText(Element).

CategoryTreeLabelProvider.java:

import org.eclipse.jface.viewers.*;
 
public class CategoryTreeLabelProvider extends LabelProvider
{
   public String getText(Object element) {
      if (element instanceof Category) {
         return ((Category) element).getName();
      }
      else if (element instanceof Link) {
         return ((Link) element).getUrl();
      }
      
      return "" + element;
   }
}

Modify your Main class:

   treeViewer.setLabelProvider(new CategoryTreeLabelProvider());

NullPointerException when auto-unboxing

This can happen when you cast a null to a primitive type. It can be hard to spot these types of errors:

Main.java:

import java.util.*;

public class Main
{
   public static void main(String []args) {
      // allow only integers to be added to the arraylist
      HashMap<String, Integer> map = new HashMap<String, Integer>();
      
      map.put("1", 10);
      map.put("2", null);
      
      int a = map.get("1");   // works fine
      int b = map.get("2");   // throws NullPointerException
   }
}

The reason for the NullPointerException is much clearer if you look
at the equivalent:

   int b = ((Integer) map.get("2")).intValue(); 

Get the number of classes loaded by the VM

With JDK 1.5 java.lang.management package:

Main.java:

import java.lang.management.*;
 
public class Main
{
   public static void main(String []args) {
      ClassLoadingMBean mbean = ManagementFactory.getClassLoadingMBean();
      int currentlyLoaded = mbean.getLoadedClassCount();      
      
      System.out.println("Currently loaded classes: " + currentlyLoaded);      
   }
}

outputs:

Currently loaded classes: 9

Using covariant return types in JDK 1.5

An argument or return type in an overridden method that is made more specialized is called to be covariant. Allowing covariant return types in Java has been in Sun’s bugparade for a long time (http://bugs.sun.com/bugdatabase/view_bug.do? bug_id=4144488. Now finally, JDK 1.5 supports it.

The protected clone() method of the Object class can be overridden, made public and support shallow or deep cloning of objects. Prior to 1.5.0, the return type of clone() had to be Object and a cast was necessary:

   Dolly d2 = (Dolly) d1.clone();

Specifying any other return type than Object caused the following exception:

clone() in Dolly cannot override clone() in java.lang.Object; attempting to use incompatible return type

Now 1.5 supports overridden methods to have a different return type as long as they are a specialization of the method in the superclass.

Main.java:

public class Main
{
   public static void main(String []args) {
      Dolly d1 = new Dolly();
      Dolly d2 = null;
       
      try {
         d2 = d1.clone();
      }
      catch(CloneNotSupportedException e) {
      }
       
      System.out.println(d1);
      System.out.println(d2);
   }
}

class Dolly implements Cloneable
{
   long fur = 123456;
    
   public Dolly clone() throws CloneNotSupportedException {
      try {
         return (Dolly) super.clone();
      }
      catch(CloneNotSupportedException e) {
         throw e;
      }
   }
    
   public String toString() {
      return ""+fur;
   }
}

Drawing a textured round filled rectangle in Swing

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private BufferedImage image; 
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      image = toBufferedImage(new javax.swing.ImageIcon("c:\djkrush.jpg").getImage());
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      Rectangle2D tr = new Rectangle2D.Double(0, 0, image.getWidth(), image.getHeight());
      TexturePaint tp = new TexturePaint(image, tr);
 
      // draw texture filled ellipse, but with antialiasing
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                           RenderingHints.VALUE_ANTIALIAS_ON);
      BasicStroke bs = new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
                           10, null, 0);
      g2d.setStroke(bs);
      g2d.setPaint(tp);
      g2d.drawRoundRect(10, 40, 150, 150, 50, 30);
   }
 
   public BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(170, 210);
      main.setVisible(true);
   }
}

Image used:

Creating an OutputStream that manipulates the data written to it

Create a class that extends from FilterOutputStream and override the method write in which you convert the original value to a new value.

Following example introduces the ChangeCaseOutputStream which will convert any character to uppercase or lowercase depending on how you instantiated the class.

Main.java:

import java.io.*;
 
public class Main {
   public static void main(String args[]) {
      try {
         FileOutputStream fos = new FileOutputStream("test.out");
         ChangeCaseOutputStream ccos = new ChangeCaseOutputStream(
                                        ChangeCaseOutputStream.UPPERCASE, fos);
         ccos.write("hello, world!".getBytes());
         ccos.flush();
         ccos.close();
      }
      catch(FileNotFoundException e) {
         System.out.println(e);
      }
      catch(IOException e) {
         System.out.println(e);
      }
   }
}
 
class ChangeCaseOutputStream extends FilterOutputStream {
   public static final int LOWERCASE = 1;
   public static final int UPPERCASE = 2;
 
   private int conversionType;
 
   public ChangeCaseOutputStream(int conversionType, OutputStream in) {
      super(in);
 
      this.conversionType = conversionType;
   }
 
   public void write(int b) throws IOException {
      if (conversionType == LOWERCASE) {
         out.write((int) Character.toLowerCase((char) b));
      }
      else if (conversionType == UPPERCASE) {
         out.write((int) Character.toUpperCase((char) b));
      }
   }
}

Converting a String to a Reader

Java provides a StringReader class expressly for this purpose. java.io.StringReader has a constructor that takes a String argument.

import java.io.StringReader;
...
String myString = 'Testing 1 2 3...';
StringReader myStringReader = new StringReader(myString);
 
// Then, use standard Reader-reading techniques
// to access the Reader
int len = -1; // Number of chars read
char [] buf = new char[256]; // Characters read from Reader
try { 
   while ((len = myStringReader.read(buf, 0, 256)) != -1) {
      System.out.println('Next chunk from Reader is ' + (new String(buf, 0, len)));
   }
} catch (IOException ioe) {
   System.err.println("Error reading from Reader :" + e.getMessage());
}

Copying a file in Java

Use FileInputStream and FileOutputStream, these classes treat files as byte streams as opposed to FileReader and FileWriter that treat files as character streams.
To copy a file, open the source file with FileInputStream and call the read() method until end-of-file, occurs when read() return -1. In the meantime, use the write method to write that byte to the newly created file.
You can make this process much more performant by using BufferedInput and BufferedOutput Streams.

import java.io.*;
 
public class copy
{
   public static void main(String []args) {
      if (args.length != 2) {
         System.out.println("Required parameter missing");
         System.exit(1);
      }
 
      try {
         FileInputStream fis = new FileInputStream(args[0]);
         FileOutputStream fos = new FileOutputStream(args[1]);
 
         int b;
         while ((b = fis.read()) != -1) fos.write(b);
 
         fos.close();
         fis.close();
      }
      catch(Exception e) {
         System.out.println(e);
      }
   }
}

Moving the mouse cursor programatically

From JDK1.3, you can use the robot class, very useful for testing purposes.
Following example shows you how to take a desktop screenshot (0,0) –> (200,200)
as well as manipulating the mouse cursor. The cursor will traverse diagonally
from the top left corner to the bottom right.

import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() throws Exception {
      Robot robot = new Robot();
      BufferedImage image = robot.createScreenCapture(new Rectangle(0, 0, 200, 200));
      getContentPane().add(new JLabel(new ImageIcon(image)));
      //setSize(200, 200);
      pack();
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }
 
   public void animateMouse() throws Exception {
      Robot robot = new Robot();
 
      double w = getSize().getWidth();
      double h = getSize().getHeight();
 
      double x1=0, y1=0;
      double dx = w/h;
      double dy = h/w;
      if (dx > dy) dx = 1; else dy = 1;
      do {
         robot.mouseMove((int) x1, (int) y1);
         x1 += dx;
         y1 += dy;
 
         try { Thread.sleep(10); } catch(InterruptedException e) { }
      } while (x1 < w || y1 < h);
   }
 
   public static void main(String args[]) throws Exception {
      Main main = new Main();
      main.show();
      main.animateMouse();
   }
}