Get started with the Java Preferences API

The Preferences API, introduced in JDK1.4, allows you to save and retrieve user and system configuration data. What you typically would do before was to save this configuration data in an XML, INI or Properties file in a specified directory known to your application. When you use the preferences API, you don’t care where this data is located. On a Windows machine, it’ll be saved in the registry, even though it is subject to change in future releases. On linux, files will be used to save your preferences (/etc/.java/.systemPrefs for system preferences and USERHOME/.java/.userPrefs for user preferences).

The Preferences API is very simple to use. Instantiate a Preferences object and use the method put to save a key, value pair. With get you can retrieve the values, even with another VM. The API uses the packagename to differentiate between preferences of different applications.

Here’s an example where you can set some preferences. When it starts up, it fills up the fields according to their values in the backing store.

comesusexamplespreferencesMain.java:

package com.esus.examples.preferences;
 
import javax.swing.border.*;
import java.util.prefs.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame 
{
   Preferences preferences;
 
   public static final String APPLICATIONPATH = "applicationpath";
   public static final String USERFONT        = "userfont";
   public static final String LASTUSERLOGIN   = "lastuserlogin";
   public static final String LDAPURL         = "ldapurl";
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      loadPreferences();
 
      JLabel appPathLabel       = new JLabel("Application Path:");
      JLabel userFontLabel      = new JLabel("User font:");
      JLabel lastUserLoginLabel = new JLabel("Last user logged in: ");
      JLabel ldapURLLabel       = new JLabel("LDAP url:");
      final JTextField appPathTf       = new JTextField(
                                  preferences.get(APPLICATIONPATH, ""));
      final JTextField userFontTf      = new JTextField(
                                  preferences.get(USERFONT, ""));
      final JTextField lastUserLoginTf = new JTextField(
                                  preferences.get(LASTUSERLOGIN, ""));
      final JTextField ldapURLTf       = new JTextField(
                                  preferences.get(LDAPURL, ""));
 
      JPanel prefsPanel = new JPanel();
      prefsPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
      prefsPanel.setLayout(new GridLayout(4, 4, 10, 10));
      prefsPanel.add(appPathLabel);
      prefsPanel.add(appPathTf);
      prefsPanel.add(userFontLabel);
      prefsPanel.add(userFontTf);
      prefsPanel.add(lastUserLoginLabel);
      prefsPanel.add(lastUserLoginTf);
      prefsPanel.add(ldapURLLabel);
      prefsPanel.add(ldapURLTf);
 
      JPanel buttonPanel = new JPanel();
      buttonPanel.setLayout(new GridLayout(1, 2, 70, 70));
 
      JButton cancelButton = new JButton("Cancel");
      cancelButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            System.exit(0);
         }
      });
 
      JButton saveButton = new JButton("Save");
      saveButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            try {
               preferences.put(APPLICATIONPATH, appPathTf.getText());
               preferences.put(USERFONT,        userFontTf.getText());
               preferences.put(LASTUSERLOGIN,   lastUserLoginTf.getText());
               preferences.put(LDAPURL,         ldapURLTf.getText());
 
               // ensure all data is flushed to the backing store
               preferences.flush();
 
               System.out.println("Preferences saved!");
            }
            catch(BackingStoreException e) {
               e.printStackTrace();
            }
         }
      });
 
      buttonPanel.add(cancelButton);
      buttonPanel.add(saveButton);
 
      getContentPane().setLayout(new BorderLayout());
      getContentPane().add(BorderLayout.CENTER, prefsPanel);
      getContentPane().add(BorderLayout.SOUTH, buttonPanel);
   }
 
   public void loadPreferences() {
      preferences = Preferences.userNodeForPackage(this.getClass());
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(350, 190);
      main.setVisible(true);
   }
}

Take a look at the Windows registry in the key \HKEY_CURRENT_USERSOFTWAREJavaSoftPrefs

.

If you want to load these preferences from another application, specify the node.

Main2.java:

import java.util.prefs.*;
 
public class Main2
{
   public static final String APPLICATIONPATH = "applicationpath";
   public static final String USERFONT        = "userfont";
   public static final String LASTUSERLOGIN   = "lastuserlogin";
   public static final String LDAPURL         = "ldapurl";
 
   public static void main(String []args) {
      String nodename = "/com/esus/examples/preferences";
 
      Preferences preferences = Preferences.userRoot().node(nodename);
      System.out.println(preferences.get(APPLICATIONPATH, ""));
      System.out.println(preferences.get(USERFONT, ""));
      System.out.println(preferences.get(LASTUSERLOGIN, ""));
      System.out.println(preferences.get(LDAPURL, ""));
   }
}

outputs:

c:application
Courier New
Joris Van den Bogaert
ldap://localhost:389

Notice also that by using userRoot you are working with preferences for that user. You can also work with system preferences (shared by all users) by specifying systemRoot.

When you perform a get, you have 2 parameters: one for the key and one for the default value. Whenever the value is not available on the backing store, the default value will be returned, if specified.

In the following example, PORT is not available on the backing store.

Main3.java:

import java.util.prefs.*;
 
public class Main3
{
   public static final String APPLICATIONPATH = "applicationpath";
   public static final String USERFONT        = "userfont";
   public static final String LASTUSERLOGIN   = "lastuserlogin";
   public static final String LDAPURL         = "ldapurl";
   public static final String PORT            = "port";
 
   public static final String DEFAULTPORT     = "2506";
 
   public static void main(String []args) {
      String nodename = "/com/esus/examples/preferences";
 
      Preferences preferences = Preferences.userRoot().node(nodename);
      System.out.println(preferences.get(APPLICATIONPATH, ""));
      System.out.println(preferences.get(USERFONT, ""));
      System.out.println(preferences.get(LASTUSERLOGIN, ""));
      System.out.println(preferences.get(LDAPURL, ""));
 
      System.out.println(preferences.get(PORT, DEFAULTPORT));
   }
}

outputs:

c:application
Courier New
Joris Van den Bogaert
ldap://localhost:389
2506

Validating a textfield using the regex package

You can use a custom InputVerifier in which you try to match the desired regular expression for that textfield.

Main.java:

import java.util.regex.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.text.*;
 
public class Main extends JFrame
{
   public Main() {
      super("JFormattedTextField REGEX example");
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      getContentPane().setLayout(new BorderLayout());
      JFormattedTextField ftf = new JFormattedTextField();
      getContentPane().add(BorderLayout.NORTH, ftf);
      ftf.setInputVerifier(new RegExFieldVerifier("[abcd]+"));
 
      getContentPane().add(BorderLayout.SOUTH, new JTextField("Normal textfield"));
      getContentPane().add(BorderLayout.CENTER, 
                               new JLabel("<HTML>REGEX USED:  [abcd]+   allowed: " +
                                          "one or more of the following characters: " +
                                          "a,b,c or d.<BR>Use the TAB key to switch!</HTML>"));
 
   }
 
   public static void main(String []args) throws Exception {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}
 
class RegExFieldVerifier extends InputVerifier {
   Pattern pattern;
 
   public RegExFieldVerifier(String regex) {
      pattern = Pattern.compile(regex);
   }
 
   public boolean verify(JComponent input) {
      if (input instanceof JFormattedTextField) {
         JFormattedTextField ftf = (JFormattedTextField)input;
         String line = ftf.getText();
         Matcher m = pattern.matcher(line);
         if (!m.matches()) 
            System.out.println("Doesn't match regular expression " + 
                               pattern.pattern());      
         return m.matches();
      }        
      return true;     
   }
 
   public boolean shouldYieldFocus(JComponent input) {
      return verify(input);
   }
}

Compressing using the GZIP algorithm at runtime in Java

Use the standard API class GZIPOutputStream. Internally, it uses Deflater to compress data. The following example asks the user a file to compress and writes the compressed stream of data to file.gzip. If you want to compress multiple files to the same outputstream, you need to call finish to write the remaining compressed data without closing the stream. Otherwise, call close.

Main.java:

import java.util.zip.*;
import java.io.*;
 
public class Main {
   public static void main(String args[]) {
      if (args.length != 1) {
         System.out.println("Usage: java Main <file>");
         System.out.println("<file>.gzip will be created");
         System.exit(1);
      }
 
      try {
         FileInputStream fis = new FileInputStream(args[0]);
         FileOutputStream fos = new FileOutputStream(args[0] + ".gzip");
 
         GZIPOutputStream gos = new GZIPOutputStream(fos); 
         byte []buffer = new byte[1024];
         int l;
         while ((l = fis.read(buffer)) >= 0) {
            gos.write(buffer, 0, l);
         }
 
         // not necessary unless you want to write more files to the GZIPOutputStream
         // gos.finish();  
         gos.close();
         fis.close();
      }
      catch(IOException e) {
         System.out.println(e);
      }
   }
}

Getting events when a JOptionPane is closing

Embed your JOptionPane in a dialog and add a PropertyChangeListener.

Main.java:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
  
public class Main
{
   public static void main(String []args) {
      JFrame frame = new JFrame();
 
      final JOptionPane pane = new JOptionPane("Are you sure you want to import this file?n" +
                                               "(try presssing the x button!)", 
                                               JOptionPane.QUESTION_MESSAGE,
                                               JOptionPane.YES_NO_CANCEL_OPTION);
      final JDialog dialog = new JDialog(frame, "Question", true);
      dialog.setContentPane(pane);
  
      dialog.addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            pane.setValue(new Integer(JOptionPane.CLOSED_OPTION));
         }
      });
 
      pane.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent e) {
            String prop = e.getPropertyName();
            if (dialog.isVisible() 
             && (e.getSource() == pane)
             && (prop.equals(JOptionPane.VALUE_PROPERTY) ||
                 prop.equals(JOptionPane.INPUT_VALUE_PROPERTY)))
            {
               System.out.println("Caught, JOptionPane is ready to close!");
               dialog.setVisible(false);
            }
         }
      });
 
      dialog.pack();
      dialog.setVisible(true);
      Object value = pane.getValue();
      System.out.println("Option " + value + " selected!");
      
      System.exit(1);
   }
}

Creating a scrollable JPanel

Create a JScrollPane and pass your panel to its constructor. Then add the scrollpane to the container. Make sure your panel has a size in case you use the null layout manager (with setSize and setPreferredSize). Here’s an example that uses a BorderLayout.

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame
{
   public Main() {
      getContentPane().setLayout(new BorderLayout());
 
      JPanel panel = createPanel();
 
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(panel));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static JPanel createPanel() {
      JPanel panel = new JPanel();
      panel.setLayout(new GridLayout(20, 4, 10, 10));
 
      for (int i=0; i<20; i++) {
         for (int j=0; j<4; j++) {
            JLabel label = new JLabel("label " + i + ", " + j);
            label.setFont(new Font("Helvetica", Font.PLAIN, 30));
            panel.add(label);            
         }
      }
 
      return panel;
   }
 
   public static void main(String [] args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   } 
} 

Creating a scrollable JTabbedPane

Starting from JDK1.4, you can set the tab layout policy to either WRAP_TAB_LAYOUT or SCROLL_TAB_LAYOUT, for example:

      tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.net.*;
 
public class Main extends JFrame implements ActionListener {
   JTabbedPane tabbedPane;
   int ntabs = 0;
 
   public Main() {
      getContentPane().setLayout(new BorderLayout());
      tabbedPane = new JTabbedPane();
      tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
 
      createTab();
 
      getContentPane().add(BorderLayout.CENTER, tabbedPane);
      setJMenuBar(createMenuBar());
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   
      setTitle("JTabbedPane Scrollable Demonstration");
      setSize(new Dimension(400, 400));
   }
 
   protected JMenuBar createMenuBar() {
      JMenuBar menuBar = new JMenuBar();
 
      JMenu menu1 = new JMenu("JTabbedPane");
      JMenuItem menuItem1 = new JMenuItem("Create new tab");
      menuItem1.addActionListener(this);
      menu1.add(menuItem1);
      JMenu menu2 = new JMenu("Change orientation");
      JMenuItem menuItem2 = new JMenuItem("TOP");
      menuItem2.addActionListener(this);
      menu2.add(menuItem2);
      JMenuItem menuItem3 = new JMenuItem("BOTTOM");
      menuItem3.addActionListener(this);
      menu2.add(menuItem3);
      JMenuItem menuItem4 = new JMenuItem("LEFT");
      menuItem4.addActionListener(this);
      menu2.add(menuItem4);
      JMenuItem menuItem5 = new JMenuItem("RIGHT");
      menuItem5.addActionListener(this);
      menu2.add(menuItem5);
      menuBar.add(menu1);
      menuBar.add(menu2);
 
      return menuBar;
   }
  
   public void actionPerformed(ActionEvent e) {
      if (e.getActionCommand().equals("Create new tab")) {
         createTab();
      }
      else if (e.getActionCommand().equals("TOP")) {
         tabbedPane.setTabPlacement(JTabbedPane.TOP);
      }
      else if (e.getActionCommand().equals("BOTTOM")) {
         tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
      }
      else if (e.getActionCommand().equals("LEFT")) {
         tabbedPane.setTabPlacement(JTabbedPane.LEFT);
      }
      else if (e.getActionCommand().equals("RIGHT")) {
         tabbedPane.setTabPlacement(JTabbedPane.RIGHT);
      }
   }
 
   protected void createTab() {
      ntabs++;
      tabbedPane.addTab("Tab #" + ntabs, new JLabel("Tab #" + ntabs));
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
}

Adding a vertical line separator to a JToolBar

The method addSeparator in the JToolBar class only adds blank space. You could add JSeparator components to your JToolBar with add but then you run into trouble when changing the orientation. In the following example, this has been solved by listening to propertyChangeEvents and changing the JSeparator orientation so that they are opposite to the JToolBar’s orientation.

Main.java:

import javax.swing.border.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.awt.*;
  
public class Main extends JFrame {
   public Main() {
      super("JToolBar example");
 
      final JTextArea textArea = new JTextArea(5, 30);
      MyJToolBar toolBar = new MyJToolBar();
 
      JButton gifButton = new JButton(new ImageIcon("gifIcon.gif"));
      JButton jpgButton = new JButton(new ImageIcon("jpgIcon.gif"));
      JButton tiffButton = new JButton(new ImageIcon("tiffIcon.gif"));
 
      gifButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            textArea.append("gifButton clicked!n");
         }
      });
  
      jpgButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            textArea.append("jpgButton clicked!n");
         }
      });
        
      tiffButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            textArea.append("tiffButton clicked!n");
         }
      });
 
      toolBar.add(gifButton);
      toolBar.add(new JToolBar.Separator());
      toolBar.add(new JSeparator(JSeparator.VERTICAL));
      toolBar.add(new JToolBar.Separator());
      toolBar.add(jpgButton);
      toolBar.add(new JToolBar.Separator());
      toolBar.add(new JSeparator(JSeparator.VERTICAL));
      toolBar.add(new JToolBar.Separator());
      toolBar.add(tiffButton);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
 
      getContentPane().setLayout(new BorderLayout());
      getContentPane().add(BorderLayout.NORTH, toolBar);
      getContentPane().add(BorderLayout.CENTER, new JScrollPane(textArea));
   }
 
   public static void main(String[] args) {
      Main main = new Main();
      main.setSize(300, 300);
      main.setVisible(true);
   }
}
 
class MyJToolBar extends JToolBar
{
   public MyJToolBar() {
      super();
      listenForOrientationChange();
   }
 
   public MyJToolBar(int orientation) {
      super(orientation);
      listenForOrientationChange();
   }
 
   public MyJToolBar(String name) {
      super(name);
      listenForOrientationChange();
   }
 
   public MyJToolBar(String name, int orientation) {
      super(name, orientation);
      listenForOrientationChange();
   }
 
   protected void listenForOrientationChange() {
      addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent evt) {
            MyJToolBar toolBar = MyJToolBar.this;
            Component[] components = toolBar.getComponents();
            for (int i=0; i<components.length; i++) {
               if (components[i] instanceof javax.swing.JSeparator) {
                  JSeparator separator = (JSeparator) components[i];
                  if (toolBar.getOrientation() == SwingConstants.HORIZONTAL) {
                     separator.setOrientation(JSeparator.VERTICAL);      
                     separator.setMaximumSize(new Dimension(2,
                                              toolBar.getPreferredSize().width));
                  }
                  else {
                     separator.setOrientation(JSeparator.HORIZONTAL);
                     separator.setMaximumSize(new Dimension(
                                              toolBar.getPreferredSize().height, 2));
                  }
               }
            }
         }
      });
   }
}

Programmatically closing a JInternalFrame

Use this:

   frame.getDesktopPane().getDesktopManager().closeFrame(frame);

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.net.*;
 
public class Main extends JFrame {
   JDesktopPane desktop;
   int nframes = 0;
 
   JMenu internalFrameMenu;
   Action closeAction = new CloseAction();
 
   public Main() {
      desktop = new JDesktopPane(); 
      setContentPane(desktop);
      setJMenuBar(createMenuBar());
      createInternalFrame(); 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   protected JMenuBar createMenuBar() {
      JMenuBar menuBar = new JMenuBar();
 
      JMenu createMenu = new JMenu("Create");
      createMenu.setMnemonic(KeyEvent.VK_C);
      JMenuItem newMenuItem = new JMenuItem("New");
      newMenuItem.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            createInternalFrame();
         }
      }); 
      newMenuItem.setMnemonic(KeyEvent.VK_N);
      createMenu.add(newMenuItem);
      menuBar.add(createMenu);
 
      internalFrameMenu = new JMenu("Close");
      internalFrameMenu.setMnemonic(KeyEvent.VK_C);
  
      menuBar.add(internalFrameMenu);     
 
      return menuBar;
   }
 
   protected void createInternalFrame() {
      nframes++;
      String title = "JInternalFrame #" + nframes;
      JInternalFrame frame = new JInternalFrame(title,
         true,    // resizable
         true,    // closable
         true,    // maximizable
         true);   // iconifiable
      frame.setVisible(true); 
      desktop.add(frame);
      frame.setSize(200, 200);
      frame.setLocation(30*nframes, 30*nframes);
      try {
         frame.setSelected(true);
      } catch (java.beans.PropertyVetoException e) {}
 
      JMenuItem menuItem = new JMenuItem(title);
      internalFrameMenu.add(menuItem);
      menuItem.addActionListener(closeAction);
      frames.put(title, frame);
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(500, 300);
      main.setVisible(true);
   }
 
   public class CloseAction extends AbstractAction
   {
      public CloseAction() {
         super("Close Action");
      }
 
      public void actionPerformed(ActionEvent ae) {
         JMenuItem menuItem = ((JMenuItem) ae.getSource());
         JInternalFrame frame = (JInternalFrame) frames.get(menuItem.getText());
         // close the frame
         frame.getDesktopPane().getDesktopManager().closeFrame(frame);
         // remove JMenuItem from JMenu
         JMenu parent = (JMenu) ((JPopupMenu) menuItem.getParent()).getInvoker();
         parent.remove(menuItem);
      }
   }
}

Assinging a shortcut key to a JButton

Swings JButton inherits from AbstractButton that defines a method setMnemonic.
You can use it as follows:

import javax.swing.event.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
   
public class Main extends JFrame
{
   public Main() throws Exception {
      JButton button = new JButton("Click or press ALT-C");
      button.setMnemonic('C');
 
      getContentPane().add(button);
      pack();
 
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent evt) {
            System.out.println("Button clicked!");
         }
      });
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String args[]) throws Exception {
      Main main = new Main();
      main.show();
   }
}

Invoking a JPopupMenu from a JComboBox

Add a MouseListener:

import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
    
public class Main extends JFrame
{ 
   public Main() {
      getContentPane().setLayout(new FlowLayout());
      
      final JComboBox combobox = new JComboBox(new String[] { "Item 1", "Item 2", "Item 3" });
      final JPopupMenu popup = new JPopupMenu();
      JMenuItem mi1 = new JMenuItem("Popup Item 1");
      JMenuItem mi2 = new JMenuItem("Popup Item 2");
      popup.add(mi1);
      popup.add(mi2);
 
      ((JButton) combobox.getComponent(0)).addMouseListener(new MouseAdapter() {
         public void mousePressed(MouseEvent me) {
            if (me.isPopupTrigger()) {
               popup.show(combobox, me.getX(), me.getY());
            }
         }
 
         public void mouseReleased(MouseEvent me) {
            if (me.isPopupTrigger()) {
               popup.show(combobox, me.getX(), me.getY());
            }
         }
      });
 
      getContentPane().add(combobox);
  
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });      
   
      setSize(new Dimension(200, 200));
   } 
 
   public static void main(String[] args) throws Exception {
      Main main = new Main();
      main.setVisible(true);
   }
}