Get started with a JTree

These sample codes will just teach you how to create a simple JTree, without worrying about how the tree is displayed. For detailed information about this, look at the other examples in this category.

DefaultMutableTreeNode

You create the simpliest JTree by constructing the hierarchy using the class DefaultMutableTreeNode. With its add method, children (of type DefaultMutableTreeNode) can be added. A child can have children as well.

Then, pass the root element to a JTree instance.

This simple example shows you how to.

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = createNodes();
      JTree tree = new JTree(root);
 
      getContentPane().add(new JScrollPane(tree));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static DefaultMutableTreeNode createNodes() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Java");
      
      DefaultMutableTreeNode j2se = new DefaultMutableTreeNode("J2SE");
      DefaultMutableTreeNode j2ee = new DefaultMutableTreeNode("J2EE");
      DefaultMutableTreeNode j2me = new DefaultMutableTreeNode("J2ME");
 
      j2se.add(new DefaultMutableTreeNode("http://java.sun.com/j2se/"));
      j2ee.add(new DefaultMutableTreeNode("http://java.sun.com/j2ee/"));
      j2me.add(new DefaultMutableTreeNode("http://java.sun.com/j2me/"));
 
      root.add(j2se);
      root.add(j2ee);
      root.add(j2me);
 
      return root;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Extending TreeModel

But if you already have an existing tree-based model, you want to use it directly (and not create a mirror that is a set of DefaultMutableTreeNodes). This way, your view stays in sync with your existing model.

You can reuse your tree-based datastructure by creating your own class that implements TreeModel as shown in the following example. The custom datastructure Category contains the data and a CategoryTreeModel passes it on to the view.

Category.java:

import java.util.*;
 
public class Category
{
   private String name;
   private Vector subCategories = new Vector();
   private Vector links = new Vector();
 
   public Category(String name) {
      this.name = name;
   }
 
   public void addSubCategory(Category category) {
      subCategories.addElement(category);
   }
 
   public void addLink(String link) {
      links.addElement(link);
   }
 
   public Vector getSubCategories() {
      return subCategories;
   }
 
   public Vector getLinks() {
      return links;
   } 
 
   public String toString() {
      return name;
   }
}

CategoryTree.java:

import javax.swing.*;
import javax.swing.tree.*;
 
public class CategoryTree extends JTree {
    CategoryTreeModel model;
 
    public CategoryTree(Category category) {
        super(new CategoryTreeModel(category));
    }
}

CategoryTreeModel.java:

import javax.swing.event.*;
import javax.swing.tree.*;
import java.util.*;
 
public class CategoryTreeModel implements TreeModel {
   private Category rootCategory;
   private Vector listeners = new Vector();
 
   public CategoryTreeModel(Category rootCategory) {
      this.rootCategory = rootCategory;
   }
 
   public Object getChild(Object parent, int index) {
      Category category = (Category) parent;
  
      // if the index falls in the subcategories vector
      if (index < category.getSubCategories().size()) {
         return category.getSubCategories().elementAt(index);
      }
 
      // else if the index falls in the links vector
      index -= category.getSubCategories().size();
      return category.getLinks().elementAt(index);
   }
 
   public int getChildCount(Object parent) {
      Category category = (Category) parent;
 
      return category.getSubCategories().size() +
             category.getLinks().size();
   }
 
   public int getIndexOfChild(Object parent, Object child) {
      Category category = (Category) parent;
 
      if (child instanceof Category) {
         return category.getSubCategories().indexOf(child);
      }
      else {
         return category.getLinks().indexOf(child);
      }
   }
 
   public Object getRoot() {
      return rootCategory;
   }
 
   public boolean isLeaf(Object node) {
      return node instanceof String;
   }
 
   public void addTreeModelListener(TreeModelListener l) {
      listeners.addElement(l);
   } 
 
   public void removeTreeModelListener(TreeModelListener l) {
      listeners.removeElement(l);
   }
 
   public void valueForPathChanged(TreePath path, Object newValue) {
      System.out.println("Value for path changed, " + newValue);
   }  
}

Main.java:

import java.net.*;
import java.awt.event.*;
  
public class Main extends JFrame
{
   public Main() {
      Category category = createCategory();
 
      CategoryTree tree = new CategoryTree(category);
  
      getContentPane().add(new JScrollPane(tree));
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static Category createCategory() {
      Category category = new Category("Java");
 
      Category j2se = new Category("j2se");
      j2se.addLink("http://java.sun.com/j2se/");
 
      Category j2ee = new Category("j2ee");
      j2ee.addLink("http://java.sun.com/j2ee/");
 
      Category j2me = new Category("j2me");
      j2me.addLink("http://java.sun.com/j2me/");
 
      category.addSubCategory(j2se);
      category.addSubCategory(j2ee);
      category.addSubCategory(j2me);
 
      return category;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Change to a Mac Look and Feel on a Windows Machine

There are two ways to implement Mac L&F on Windows. The first consists of modifying the main L&F class to return true when the isSupportedLookAndFeel is called. This is against the Swing/JDK license agreement, though.

Another way is to use a 3rd party Mac look & feel. Check out the website in the related URLs section for more information. Remember that you can dynamically load a look and feel without having to modify a properties file.

Turning off DTD validation

As soon as you create the DocumentBuilderFactory, call the method setValidating and set it to false.

Try out following example and set it to true to see the parsing errors.

customers.dtd (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<!ELEMENT customer (name, addresses+, email)+ >
<!ATTLIST customer custid CDATA #REQUIRED>
 
<!ELEMENT name (#PCDATA)>
 
<!ELEMENT addresses (addline1, addline2, zip, location, state)>
<!ELEMENT addline1 (#PCDATA)>
<!ELEMENT addline2 (#PCDATA)>
<!ELEMENT zip (#PCDATA)>
<!ELEMENT location (#PCDATA)>
<!ELEMENT state (#PCDATA)>
 
<!ELEMENT email (#PCDATA)>

customers.xml (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE customers SYSTEM "customers.dtd">
<customers>
   <customer id="C12345" type="prio1">
      <name>Joris Van den Bogaert</name>
      <address>
         <addressline>Handelskaai 3</addressline>
         <zip>1000</zip>
         <location>Brussels</location>
         <country>BELGIUM</country>
      </address>
   </customer>
</customers>

Main.java:

import org.w3c.dom.*;
  
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
 
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         dbf.setValidating(true);
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("customers.xml"));
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

List the children of a directory using the JNDI file system provider

This example lists the files in the c:\temp directory.

Main.java:

import javax.naming.*;
import java.util.*;
import java.io.*;
 
public class Main
{
   public static void main(String []args) {
      try {
         Properties properties = new Properties();
         properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
         properties.put(Context.PROVIDER_URL, "file:///");
 
         Context ctx = new InitialContext(properties);
 
         // List the objects 
         NamingEnumeration enum = ctx.list("c:\temp");
         while (enum.hasMore()) {
            NameClassPair ncPair = (NameClassPair) enum.next();
            System.out.println(ncPair.getName() + "t" + ncPair.getClassName());
         }
         ctx.close();
 
      }
      catch(NamingException ne) {
         ne.printStackTrace();
      }
   }
}

Notice that every element that the method list returns is of type NameClassPair. If you actually want to do an operation on a child, you would have to get it with lookup.

If you want to perform an operation on all the children, you can use the alternative method listBindings which, instead of NameClassPair, returns Binding instances. Binding is a subclass of NameClassPair that also contains the object itself (accessible with getObject).

Main.java:

import javax.naming.*;
import java.util.*;
import java.io.*;
 
public class Main
{
   public static void main(String []args) {
      try {
         Properties properties = new Properties();
         properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
         properties.put(Context.PROVIDER_URL, "file:///");
 
         Context ctx = new InitialContext(properties);
 
         // List the objects 
         NamingEnumeration enum = ctx.listBindings("c:\temp");
         while (enum.hasMore()) {
            Binding binding = (Binding) enum.next();
            System.out.println(binding.getName() + "t" + binding.getClassName());
            System.out.println(binding.getObject());
         }
         ctx.close();
 
      }
      catch(NamingException ne) {
         ne.printStackTrace();
      }
   }
}

Programmatically get information about your database driver

Main.java:

import java.util.*;
import java.sql.*;
  
public class Main {
   public static void main(String []args) throws Exception {
      try {
         Class.forName("org.gjt.mm.mysql.Driver").newInstance();
         Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.0.1/esus", 
                                                       "joris",
                                                       "mypass");
         DatabaseMetaData dbMeta = conn.getMetaData(); 
 
         System.out.println ("Database Product Name : " +
                                 dbMeta.getDatabaseProductName());
         System.out.println ("Database Product Version: " +
                                 dbMeta.getDatabaseProductVersion());
         System.out.println ("Database Driver Name : " +
                                 dbMeta.getDriverName());
         System.out.println ("Database Driver Version : " +
                                 dbMeta.getDriverVersion());
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

outputs:

Database Product Name : MySQL
Database Product Version: 3.23.42
Database Driver Name : Mark Matthews' MySQL Driver
Database Driver Version : 2.0.4

Using a shutdown hook

To gain control over when you application shuts down (eg. to close database connections), you can use the 1.3 method addShutdownHook in the Runtime class and pass it a thread object. The JVM will execute the thread when the application is about the end.

eg.

public class Main
{
   public static void main(String args[]) {

      Runtime.getRuntime().addShutdownHook(new Thread() {
         public void run() {
            System.out.println("Shutting down...");
         }
      });

      System.out.println("press ctrl-c to exit!");
      while (true) ;
   }
}

Native byte order on your machine

Simple, in JDK1.4+, use java.nio.ByteOrder.nativeOrder()

Main.java:

import java.nio.*;
 
public class Main
{
   public static void main(String []args) {
      ByteOrder bo = ByteOrder.nativeOrder();
      
      System.out.println("Native byte order of your platform is " + bo);
   }
}

outputs on my win machine:

Native byte order of your platform is LITTLE_ENDIAN

Showing the trademark symbol in a JLabel

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
   
public class Main extends JFrame {
   public Main() {
      getContentPane().setLayout(new FlowLayout());
 
      final JLabel label = new JLabel("Javau2122");
      getContentPane().add(label);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent event) {
            System.exit(0);   
         }      
      });
 
      pack();
   }
 
   public static void main(String[] args) {
      (new Main()).show();
   }
}

Creating a label with SWT

Main.java:

import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.*;
 
public class Main {
   public static void main(String[] args) {
      Display display = new Display();
      Shell shell = new Shell(display);

      // pos x, pos y, width, height
      shell.setBounds(200, 200, 300, 200);
      shell.setText("Label Demonstration");
      shell.setLayout(new GridLayout());

      Label label = new Label(shell, SWT.CENTER);
      label.setText("This is a label");

      shell.open();

      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
   }
}

Using a drop down combobox in SWT

Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
 
public class Main {
   public static void main(String[] args) {
      Display display = new Display();
      Shell shell = new Shell(display);
 
      // pos x, pos y, width, height
      shell.setBounds(200, 200, 300, 200);
      shell.setText("SWT Combobox Demonstration");
      shell.setLayout(new GridLayout());
 
      String[] comboData = { "one", "two", "three", "four", "five",
                             "six", "seven", "eight", "nine", "ten",
                             "eleven", "twelve", "thirtheen", "fourteen",
                             "fifteen", "sixteen", "seventeen", "eighteen",
                             "nineteen", "twinty" };
 
      Group comboGroup = new Group(shell, SWT.NULL);
      GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 1;
      comboGroup.setLayout(gridLayout);
      comboGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      comboGroup.setText("Editable Combo");
       
      Combo combo = new Combo(comboGroup, SWT.DROP_DOWN);
      SelectionListener selectionListener = new SelectionAdapter () {
         public void widgetSelected(SelectionEvent event) {
            Combo combo = ((Combo) event.widget);
            System.out.print(combo.getText());
            System.out.println(" selected = " + combo.getSelection());
         };
      };
      combo.addSelectionListener(selectionListener);
      combo.setItems(comboData);
       
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
   }
}