Wednesday, January 30, 2008

Dialog Modality

his Tech Tip reprinted with permission by java.sun.com

Top-level popup windows in "Java-speak" are called dialog boxes (or simply "dialogs"). They are typically used to interact with a user -- either to display a message or to accept user input. Before Java SE 6, dialog boxes were modeless by default, with an option to be modal. When a dialog box is modal, other windows in the application are blocked from accepting input, unless they have the dialog box as their owner. After a user reacts accordingly to a dialog box, that is, by entering input or just closing the dialog, the other windows of the application become accessible again.

Java SE 6 gives you more options regarding dialog modality. No longer are you limited in scope to one level of modality: on or off. Now you have four distinct settings defined by the new Dialog.ModalityType enumeration:

  • MODELESS
  • APPLICATION_MODAL
  • DOCUMENT_MODAL
  • TOOLKIT_MODAL

First let's look at MODELESS and APPLICATION_MODAL. A MODELESS setting means a modeless dialog box. As before, a modeless dialog box does not block input to any other window of the application. Another modal dialog box could block input to it, but a modeless one has no effect on another. If you call the setModal() method of the Dialog class with a value of false, it sets the Dialog.ModalityType to MODELESS.

The APPLICATION_MODAL setting means a modal dialog box. As before, all windows of the application that do not have the modal dialog box in their owner hierarchy are blocked from getting focus. This means that new windows can be created from the modal dialog and will accept input. However, new windows created from other pre-existing windows cannot. If you call the setModal() method of Dialog with a value of true, it sets the modality of the Dialog to DEFAULT_MODALITY_TYPE, which equates to APPLICATION_MODAL. This keeps legacy code valid, though new code should use the new setModalityType() method.

At this point you might ask what if you don't explicitly specify a modality? The answer is that the initial modality is modeless. Also, if you specify a boolean modality, it produces the same settings as calling setModal() with that boolean value. The last option is explicitly setting the modality, which has the obvious effect.

DOCUMENT_MODAL and TOOLKIT_MODAL are where things get interesting. DOCUMENT_MODAL allows you to have different sets of windows that are modal. For instance, you can have a modal application window that displays a help window. Provided that it has a top-level window that is not part of the main application hierarchy, the help window can be modal. In addition, the help window can create other modal windows that have a modality separate from the main window and separate from any modal dialogs that the help window creates. Having a modal application that displays a modal help window is a common need when utilizing the JavaHelp library. It's typical that users want to be able to interact with help, even when the current window is modal. This need wasn't adequately met prior to support for DOCUMENT_MODAL because the main application window and help window had different owner hierarchies.

Think of TOOLKIT_MODAL as APPLICATION_MODAL, where the application is the browser. (In this paragraph what's said about applets also applies to applications started through Java WebStart technology.) This setting allows one applet in a browser to be modal, blocking other applets from accepting input. That's because all the applets are loaded with the same Toolkit. Your applet must have AWTPermission.toolkitModality enabled for TOOLKIT_MODAL to work.

In addition to setting the modality type of a window, you can set the modal exclusion type by calling the setModalExclusionType() method of Window. This allows you to exclude certain windows from behaving according to the pertinent modality type. The setModalExclusionType() method accepts one of three values from the Dialog.ModalExclusionType enumeration:

  • NO_EXCLUDE
  • APPLICATION_EXCLUDE
  • TOOLKIT_EXCLUDE

The NO_EXCLUDE option means no modal exclusion. The window behaves according to its current modality type. The other two settings allow you to use a modality type, but also allow specific windows to accept input focus. The APPLICATION_EXCLUDE setting specifies that at the application level, the window will not behave according to its modality. TOOLKIT_EXCLUDE specifies that at both the application and Toolkit level, the window will not behave according to its modality. There is no way to have a window exclude behavior at the Toolkit level, but not at the application level.

Before using either the modality types or the exclusion option, you can ask the Toolkit if either is supported. To discover if a particular modality is supported, use the boolean isModalityTypeSupported(Dialog.ModalityType modalityType) method. To discover if an exclusion type is supported, use the boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType modalExclusionType) method.

Here's a program, DualModal, that displays two frames that use the DOCUMENT_MODAL setting. Each frame has a button that creates a document modal option pane, accepting input. The label of the selected button changes to the text that was entered when the option pane closes.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class DualModal {
public static void main(String args[]) {
Runnable runner = new Runnable() {
public void run() {
JFrame frame1 = new JFrame("Left");
JFrame frame2 = new JFrame("Right");
frame1.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
frame2.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
JButton button1 = new JButton("Left");
JButton button2 = new JButton("Right");
frame1.add(button1, BorderLayout.CENTER);
frame2.add(button2, BorderLayout.CENTER);
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton source = (JButton)e.getSource();
String text = getNewText(source);
if (!JOptionPane.UNINITIALIZED_VALUE.equals(text)
&& text.trim().length() > 0) {
source.setText(text);
}
}
};
button1.addActionListener(listener);
button2.addActionListener(listener);
frame1.setBounds(100, 100, 200, 200);
frame1.setVisible(true);
frame2.setBounds(400, 100, 200, 200);
frame2.setVisible(true);
}
};
EventQueue.invokeLater(runner);
}
private static String getNewText(Component parent) {
JOptionPane pane = new JOptionPane(
"New label", JOptionPane.QUESTION_MESSAGE
);
pane.setWantsInput(true);
JDialog dialog = pane.createDialog(parent, "Enter Text");
// Uncomment line and comment out next
// to see application modal
// dialog.setModalityType(
// Dialog.ModalityType.APPLICATION_MODAL);
dialog.setModalityType(
Dialog.ModalityType.DOCUMENT_MODAL);
dialog.setVisible(true);
return (String)pane.getInputValue();
}
}

Notice how you can interact with the top-level dialog, but not the frame under either of them when the dialog is shown.

Here is what the initial pair of frames look like:


Image

And here are the two frames with their respective option panes:


Image

You might think that changing the setModalityType() line to use APPLICATION_MODAL would allow you to interact with both option frames simultaneously. It won't. You need to finish using one option frame before you can bring up the other.

Two points worth mentioning here. Changing the modality of an already displayed window has no effect. You must hide the dialog box and make it visible again for the new modality setting to take effect.

Also, prior to Java SE 6, any AWT Window or subclass could use the setAlwaysOnTop() method of Window to request that it is always displayed on top. This is not the same as modal and does not prevent other windows from getting input focus.

For more information on dialog modality, see the article The New Modality API in Mustang.

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.

Monday, January 28, 2008

How to use List interface

List interface is an extension of Collection interface. List interface indicates the behavior of the collection of objects. It allows duplicate objects and one or more elements to be null.

Useful methods of the List Interface:

Method

Usage

add()

Adds an objects to the collection

clear()

Removes all objects from the collection.

contains()

Returns true if a special object is an element with in the collection.

get()

Returns the element at the specified index position in this collection.

isEmpty()

Returns true if the collection has no elements.

listIterator()

Returns a ListItertor object for the collection which may then be used to retrieve an object.

Remove()

Removes the element at the specified index position in this collection.

size()

Returns the number of elements in the collection.

In this code ListIterator is used for reading the objects of the list. It allows reading objects from the collection in both the forward and backward directions.

import java.util.*;

public class DemoList {

public static void main(String[] args) {

List ls = new LinkedList();

for(int i=1; i<=5; i++){
ls.add(new StringBuffer("Object " + i));
}

//display how many objects are in the collection
System.out.println("The collection has " + ls.size() + "objects");

//Instantiate a ListIterator
ListIterator li = ls.listIterator();
System.out.println("Forward Reading");

//Forward direction
while(li.hasNext()){
System.out.println(" " + li.next());
}

System.out.println("Backward Reading");

//backword direction
while(li.hasPrevious()){
System.out.println(" " + li.previous());
}
}

}

Output Screen:

The collection has 5objects
Forward Reading
Object 1
Object 2
Object 3
Object 4
Object 5
Backward Reading
Object 5
Object 4
Object 3
Object 2
Object 1

Tuesday, January 22, 2008

How to copy a directory from one location to another location

This Java tip demonstrates a method of copying a directory from one location to another. Copying is done from sourcedirectory to targetdirectory.


// If targetLocation does not exist, it will be created.
public void copyDirectory(File sourceLocation , File targetLocation)
throws IOException {

if (sourceLocation.isDirectory()) {
if (!targetLocation.exists()) {
targetLocation.mkdir();
}

String[] children = sourceLocation.list();
for (int i=0; i) {
copyDirectory(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else {

InputStream in = new FileInputStream(sourceLocation);
OutputStream out = new FileOutputStream(targetLocation);

// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}

Saturday, January 19, 2008

Finding Greatest Common Divisor recursively

In mathematics, the greatest common divisor (gcd), sometimes known as the greatest common factor (gcf) or highest common factor (hcf), of two non-zero integers, is the largest positive integer that divides both numbers.

The greatest common divisor of a and b is written as gcd(a, b), or sometimes simply as (a, b). For example, gcd(12, 18) = 6, gcd(−4, 14) = 2 and gcd(5, 0) = 5. Two numbers are called coprime or relatively prime if their greatest common divisor equals 1. For example, 9 and 28 are relatively prime.

The code below shows how to implement gcd function recursively.

/**
* Return the greatest common divisor
*/

public static long gcd(long a, long b) {

if (b==0)
return a;
else
return gcd(b, a % b);
}

Tuesday, January 15, 2008

Use of clone method - cloning objects

The reason for making a local copy of an object is if you’re going to modify that object and you don’t want to modify the caller’s object. If you decide that you want to make a local copy, you simply use the clone() method to perform the operation. For example, the standard library class ArrayList overrides clone(), so we can call clone() for ArrayList:
import java.util.*;

class Int {

private int i;

public Int(int ii) { i = ii; }

public void increment() { i++; }

public String toString() {
return Integer.toString(i);
}
}

public class DemoCloning {

public static void main(String[] args) {
ArrayList al = new ArrayList();

for(int i = 0; i < 10; i++ )
al.add(new Int(i));

System.out.println("al: " + al);

ArrayList al1 = (ArrayList)al.clone();

// Increment all al1's elements:
for(Iterator e = al1.iterator(); e.hasNext(); )
((Int)e.next()).increment();

// See if it changed al's elements:
System.out.println("al: " + al);
}
}

The clone() method produces an Object, which must then be recast to the proper type. This example shows how ArrayList’s clone() method does not automatically try to clone each of the objects that the ArrayList contains—the old ArrayList and the cloned ArrayList are aliased to the same objects. This is often called a shallow copy, since it’s copying only the “surface” portion of an object. The actual object consists of this “surface,” plus all the objects that the references are pointing to, plus all the objects those objects are pointing to, etc. This is often referred to as the “web of objects.” Copying the entire mess is called a deep copy. You can see the effect of the shallow copy in the output, where the actions performed on al1 affect al:

al: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
al: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

How to use Key Events in Swing

Sunday, January 13, 2008

How to use Mouse Events in Swing

Mouse events are generated by the following types of user interaction:

  • A mouse click
  • A mouse entering a component's area
  • A mouse leaving a component's area

Any component can generate these events, and a class must implement MouseListener interface to support them.

The following example shows how to use mouse events in Swing:

import javax.swing.*;

import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.Color;
import java.awt.Dimension;

import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;

public class MouseEventDemo extends JPanel
implements MouseListener {
BlankArea blankArea;
JTextArea textArea;
final static String newline = "\n";

public MouseEventDemo() {
super(new GridBagLayout());
GridBagLayout gridbag = (GridBagLayout)getLayout();
GridBagConstraints c = new GridBagConstraints();

c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1.0;
c.weighty = 1.0;

c.insets = new Insets(1, 1, 1, 1);
blankArea = new BlankArea(new Color(0.98f, 0.97f, 0.85f));
gridbag.setConstraints(blankArea, c);
add(blankArea);

c.insets = new Insets(0, 0, 0, 0);
textArea = new JTextArea();
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(200, 75));
gridbag.setConstraints(scrollPane, c);
add(scrollPane);

//Register for mouse events on blankArea and the panel.
blankArea.addMouseListener(this);
addMouseListener(this);

setPreferredSize(new Dimension(450, 450));
setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}

public void mousePressed(MouseEvent e) {
saySomething("Mouse pressed (# of clicks: "
+ e.getClickCount() + ")", e);
}

public void mouseReleased(MouseEvent e) {
saySomething("Mouse released (# of clicks: "
+ e.getClickCount() + ")", e);
}

public void mouseEntered(MouseEvent e) {
saySomething("Mouse entered", e);
}

public void mouseExited(MouseEvent e) {
saySomething("Mouse exited", e);
}

public void mouseClicked(MouseEvent e) {
saySomething("Mouse clicked (# of clicks: "
+ e.getClickCount() + ")", e);
}

void saySomething(String eventDescription, MouseEvent e) {
textArea.append(eventDescription + " detected on "
+ e.getComponent().getClass().getName()
+ "." + newline);
textArea.setCaretPosition(textArea.getDocument().getLength());
}

/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);

//Create and set up the window.
JFrame frame = new JFrame("MouseEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create and set up the content pane.
JComponent newContentPane = new MouseEventDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);

//Display the window.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}


import javax.swing.*;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Graphics;

public class BlankArea extends JLabel {
Dimension minSize = new Dimension(100, 100);

public BlankArea(Color color) {
setBackground(color);
setOpaque(true);
setBorder(BorderFactory.createLineBorder(Color.black));
}

public Dimension getMinimumSize() {
return minSize;
}

public Dimension getPreferredSize() {
return minSize;
}
}

Wednesday, January 09, 2008

How to use PixelGrabber class to acquire pixel data from an Image object

PixelGrabber class available in java.awt.image packate can be used to access pixels of an Image object. PixelGrabber class can acquire pixel data synchronously or asynchronously. It can store pixel values in a user-specified array or create a suitable array itself.

The following example shows how to use PixelGrabber class to get pixel data from an Image object.

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.PixelGrabber;

public class PixelGrabberTest {

public PixelGrabberTest() {
}

public static void processImage(String inFile, String outFile) {

Image image = Toolkit.getDefaultToolkit().getImage(inFile);

try {

PixelGrabber grabber =
new PixelGrabber(image, 0, 0, -1, -1, false);

if (grabber.grabPixels()) {
int width = grabber.getWidth();
int height = grabber.getHeight();

if (isGreyscaleImage(grabber)) {
byte[] data = (byte[]) grabber.getPixels();

// Process greyscale image ...

}
else {
int[] data = (int[]) grabber.getPixels();

// Process Color image

}
}
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
}

public static final boolean isGreyscaleImage(PixelGrabber pg) {
return pg.getPixels() instanceof byte[];
}

public static void main(String args[]) {

if (args.length > 1) {
processImage(args[0], args[1]);
System.exit(0);
} else {
System.err.println(
"usage: java PixelGrabberTest ");

System.exit(2);
}

}
}

Saturday, January 05, 2008

What is a Java superclass

A Java superclass is a class which gives a method or methods to a Java subclass.

A Java class may be either a subclass, a superclass, both, or neither!

The Cat class in the following example is the subclass and the Animal class is the superclass.

public class Animal {

public static void hide() {
System.out.println("The hide method in Animal.");
}

public void override() {
System.out.println("The override method in Animal.");
}
}

public class Cat extends Animal {

public static void hide() {
System.out.println("The hide method in Cat.");
}

public void override() {
System.out.println("The override method in Cat.");
}

public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = (Animal)myCat;
myAnimal.hide();
myAnimal.override();
}
}

Thursday, January 03, 2008

How to use Focus Events in Swing

Focus events occur when any component gains or loses input focus on a graphical user interface. Focus applies to all components that can recieve input.

To handle a focus event, a class must implement the FocusListener interface.

The following example shows how to use focus events in Swing:

/*
* FocusEventDemo.java is a 1.4 example that requires
* no other files.
*/

import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class FocusEventDemo extends JPanel
implements FocusListener {
final static String newline = "\n";
JTextArea display;

public FocusEventDemo() {
super(new GridBagLayout());
GridBagLayout gridbag = (GridBagLayout)getLayout();
GridBagConstraints c = new GridBagConstraints();

c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0; //Make column as wide as possible.
JTextField textField = new JTextField("A TextField");
textField.setMargin(new Insets(0,2,0,2));
textField.addFocusListener(this);
gridbag.setConstraints(textField, c);
add(textField);

c.weightx = 0.1; //Widen every other column a bit, when possible.
c.fill = GridBagConstraints.NONE;
JLabel label = new JLabel("A Label");
label.setBorder(BorderFactory.createEmptyBorder(0,5,0,5));
label.addFocusListener(this);
gridbag.setConstraints(label, c);
add(label);

String comboPrefix = "ComboBox Item #";
final int numItems = 15;
Vector vector = new Vector(numItems);
for (int i = 0; i <>) {
vector.addElement(comboPrefix + i);
}
JComboBox comboBox = new JComboBox(vector);
comboBox.addFocusListener(this);
gridbag.setConstraints(comboBox, c);
add(comboBox);

c.gridwidth = GridBagConstraints.REMAINDER;
JButton button = new JButton("A Button");
button.addFocusListener(this);
gridbag.setConstraints(button, c);
add(button);

c.weightx = 0.0;
c.weighty = 0.1;
c.fill = GridBagConstraints.BOTH;
String listPrefix = "List Item #";
Vector listVector = new Vector(numItems);
for (int i = 0; i <>) {
listVector.addElement(listPrefix + i);
}
JList list = new JList(listVector);
list.setSelectedIndex(1); //It's easier to see the focus change
//if an item is selected.
list.addFocusListener(this);
JScrollPane listScrollPane = new JScrollPane(list);
//We want to prevent the list's scroll bars
//from getting the focus - even with the keyboard.
//Note that in general we prefer setRequestFocusable
//over setFocusable for reasons of accessibility,
//but this is to work around bug #4866958.
listScrollPane.getVerticalScrollBar().setFocusable(false);
listScrollPane.getHorizontalScrollBar().setFocusable(false);
gridbag.setConstraints(listScrollPane, c);
add(listScrollPane);

c.weighty = 1.0; //Make this row as tall as possible.
c.gridheight = GridBagConstraints.REMAINDER;
//Set up the area that reports focus-gained and focus-lost events.
display = new JTextArea();
display.setEditable(false);
//The method setRequestFocusEnabled prevents a
//component from being clickable, but it can still
//get the focus through the keyboard - this ensures
//user accessibility.
display.setRequestFocusEnabled(false);
display.addFocusListener(this);
JScrollPane displayScrollPane = new JScrollPane(display);

//Work around for bug #4866958.
displayScrollPane.getHorizontalScrollBar().setFocusable(false);
displayScrollPane.getVerticalScrollBar().setFocusable(false);
gridbag.setConstraints(displayScrollPane, c);
add(displayScrollPane);

setPreferredSize(new Dimension(450, 450));
setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}

public void focusGained(FocusEvent e) {
displayMessage("Focus gained", e);
}

public void focusLost(FocusEvent e) {
displayMessage("Focus lost", e);
}

void displayMessage(String prefix, FocusEvent e) {
display.append(prefix
+ (e.isTemporary() ? " (temporary):" : ":")
+ e.getComponent().getClass().getName()
+ "; Opposite component: "
+ (e.getOppositeComponent() != null ?
e.getOppositeComponent().getClass().getName() : "null")
+ newline);
display.setCaretPosition(display.getDocument().getLength());
}

/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);

//Create and set up the window.
JFrame frame = new JFrame("FocusEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//Create and set up the content pane.
JComponent newContentPane = new FocusEventDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);

//Display the window.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}