Swing : Java Foundation Classes
- JFC Overview (JFC pronounced as Swing)
- Swing Packages Overview
- Component Hierarchy
- Understanding JPanel, Icon, JLabel, JButton,JTabbedPane, JMenu, PopMenu,Toolbar etc. With Example
JFC Overview (JFC pronounced as Swing) |
Sun Microsystems is leveraging the technology of NetscapeTM Communications, IBM, and Lighthouse Design (now owned by Sun) to create a set of Graphical User Interface (GUI) classes that integrate with JDKTM 1.1.5+, are standard with the Java ® 2 platform and provide a more polished look and feel than the standard AWT component set. The collection of APIs coming out of this effort, called the Java Foundation Classes (JFC), allows developers to build full-featured enterprise-ready applications.
JFC is composed of five APIs: AWT, JavaTM 2D, Accessibility, Drag and Drop, and Swing. The AWT components refer to the AWT as it exists in JDK versions 1.1.2 and later. Java 2D is a graphics API based on technology licensed from IBM/Taligent. It is currently available with the Java® 2 Platform (and not usable with JDK 1.1). The Accessibility API provides assistive technologies, like screen magnifiers, for use with the various pieces of JFC. Drag and Drop support is part of the next JavaBeanTM generation, "Glasgow," and is also available with the Java® 2 platform.
Swing includes a component set that is targeted at forms-based applications. Loosely based on Netscape’s acclaimed Internet Foundation Classes (IFC), the Swing components have had the most immediate impact on Java development. They provide a set of well-groomed widgets and a framework to specify how GUIs are visually presented, independent of platform. At the time this was written, the Swing release is at 1.1 (FCS).
Swing Packages Overview |
Swing can expand and simplify your development of cross-platform applications.
The Swing collection consists of seventeen packages, each of which has its own distinct purpose.
- javax.swing The high level swing package primarily consists of components, adapters, default component models, and interfaces for all the delegates and models.
- javax.swing.borderThe border package declares the Border interface and classes, which define specific border rendering styles.
- javax.swing.colorchooserThe colorchooser package contains support classes for the color chooser component.
- javax.swing.eventThe event package is for the Swing-specific event types and listeners. In addition to the java.awt.event types, Swing components can generate their own event types.
- javax.swing.filechooserThe filechooser package contains support classes for the file chooser component.
- javax.swing.plaf.*The pluggable look-and-feel (PLAF) packages contain the User Interface (UI) classes (delegates) which implement the different look-and-feel aspects for Swing components. There are also PLAF packages under the javax.swing.plaf hierarchy.
- javax.swing.tableThe table package contains the support interfaces and classes the Swing table component.
- javax.swing.textThe text package contains the support classes for the Swing document framework.
- javax.swing.text.html.*The text.html package contains the support classes for an HTML version 3.2 renderer and parser.
- javax.swing.text.rtfThe text.rtf package contains the support classes for a basic Rich Text Format (RTF) renderer.
- javax.swing.treeThe tree package contains the interfaces and classes which support the Swing tree component.
- javax.swing.undoThe undo package provides the support classes for implementing undo/redo capabilities in a GUI.
- javax.accessibilityThe JFC Accessibility package is included with the Swing classes. However, its usage is not discussed here.
Component Hierarchy |
Swing Component Hierarchy
Click here to see the whole Component Classes Hierarchy
Understanding Icon, JButton,JTabbedPane, JMenu, PopMenu,Toolbar Example |
JPanel
- The first widget to discuss is JPanel. It is a lightweight Panel object offering built-in support for double buffering.
- When buffering is enabled, through the constructor, all the drawing operations of components within the panel will be drawn to an off-screen drawing area prior to being drawn to the screen.
- The JPanel class is used in most of the examples.
Icons
- An Icon is used to describe fixed-size pictures, or glyphs. Typically, you embed icons in a JButton or other JComponent.
- Objects that can act as icons implement the Icon interface, shown below.
- It contains a paintIcon() method that specifies a drawing origin.
- You render the picture specified in the paintIcon() method in a rectangle whose size cannot exceed a rectangle with an origin at (x, y), a width of getIconWidth(), and a height of getIconHeight().
- The Component parameter to paintIcon() is not usually used, unless you need to specify additional information, such as a font or color.
Icon Interface
public interface Icon {
void paintIcon(
Component c, Graphics g, int x, int y);
int getIconWidth();
int getIconHeight();
}
The ImageIcon class is an implementation of Icon that creates an Icon from an Image.
Icon tinyPicture = new ImageIcon("TinyPicture.gif");
Alternatively, the ImageIcon constructor can take an Image or URL object or byte array as its parameter, with an optional String description parameter. One nice thing about ImageIcon is it checks a cache before retrieving the image file.
Swing uses ImageIcon rather than Image for two reasons:
- An Image loads asynchronously, creating the need to monitor the loading process (with MediaTracker).
- An Image is not serializable.
- In addition to using ImageIcon, you can implement the interface yourself to create your own icons:
Icon Example
public class RedOval implements Icon {
public void paintIcon (Component c, Graphics g,
int x, int y) {
g.setColor(Color.red);
g.drawOval (x, y, getIconWidth(), getIconHeight());
}
public int getIconWidth() {
return 10;
}
public int getIconHeight() {
return 10;
}
}
JLabel
A JLabel is a single line label similar to java.awt.Label. Additional functionality that a JLabel has is the ability to:
- Add an Icon
- Set the vertical and horizontal position of text relative to the Icon
- Set the relative position of contents within component
JLabel Example1
import javax.swing.*;
import java.awt.*;
class JLabelDemo
{
public static void main(String[] args)
{
LabelPanel p=new LabelPanel ();
JFrame f=new JFrame();
f.add(p);
f.setVisible(true);
f.setSize(200,50);
}
}
class LabelPanel extends JPanel {
public LabelPanel() {
// Create and add a JLabel
JLabel plainLabel = new JLabel("Plain Small Label");
add(plainLabel);
// Create a 2nd JLabel
JLabel fancyLabel = new JLabel("Fancy Big Label");
// Instantiate a Font object to use for the label
Font fancyFont =
new Font("Serif", Font.BOLD | Font.ITALIC, 32);
// Associate the font with the label
fancyLabel.setFont(fancyFont);
// Create an Icon
Icon tigerIcon = new ImageIcon("SmallTiger.gif");
// Place the Icon in the label
fancyLabel.setIcon(tigerIcon);
// Align the text to the right of the Icon
fancyLabel.setHorizontalAlignment(JLabel.RIGHT);
// Add to panel
add(fancyLabel);
}
}
JButton
- A JButton can be instantiated and used in a GUI just like a java.awt.Button.
- It behaves like an AWT 1.1 Button, notifying ActionListener list elements when pushed.
JButton Example1
import javax.swing.*;
import java.awt.*;
class JButtonDemo1
{
public static void main(String[] args)
{
ButtonPanel p=new ButtonPanel ();
JFrame f=new JFrame("JavaSkool Example");
f.add(p);
f.setVisible(true);
f.setSize(200,50);
}
}
class ButtonPanel extends JPanel {
public ButtonPanel () {
JButton myButton = new JButton("Login");
add(myButton);
}
}
Also, the JButton has support for an embedded Icon, specified in the constructor, or via the setIcon() method. This creates an image button;
JButton Example2
import javax.swing.*;
import java.awt.*;
class JButtonDemo2
{
public static void main(String[] args)
{
ButtonPanel p=new ButtonPanel ();
JFrame f=new JFrame("JavaSkool Example");
f.add(p);
f.setVisible(true);
f.setSize(200,50);
}
}
class ButtonPanel extends JPanel {
public ButtonPanel() {
Icon tigerIcon = new ImageIcon("rab1.png");
JButton myButton = new JButton("Tiger", tigerIcon);
add(myButton);
}
}
AbstractButton
- While the AbstractButton isn’t a class you use directly, several of the more common JComponent classes inherit much of their shared behavior from this object.
- For instance, the icon usage methods getIcon() and setIcon() come from AbstractButton. (The methods are also available elsewhere.)
- Some of the other common features are listed below:
- setMnemonic() – Add a keyboard accelerator to a text label, use the VK_* constants from KeyEvent to specify the key
- doClick() – Programmatically, select the button
- setDisabledIcon(), setDisabledSelectedIcon(), setPressedIcon(), setRolloverIcon(), setRolloverSelectedIcon(), setSelectedIcon() – Change the displayed Icon, based on the button state (in addition to setIcon())
- setVerticalAlignment(), setHorizontalAlignemnt() – Anchors icon/text in different areas of button
- setVerticalTextPosition(), setHorizontalTextPosition() – Positions text in different areas around icon. Both setXXXAlignment() and setYYYTextPosition() rely on the SwingConstants interface for the area placement settings.
JCheckBox
- A JCheckBox is similar to an AWT Checkbox that is not in a CheckboxGroup.
- Although Swing provides a default graphic to signify JCheckBox selection, you also can specify your own Icon objects for both the checked and unchecked state.
JCheckBox Example
import javax.swing.*;
import java.awt.*;
class JCheckBoxDemo
{
public static void main(String[] args)
{
CheckboxPanel p=new CheckboxPanel ();
JFrame f=new JFrame("JavaSkool Example");
f.add(p);
f.setVisible(true);
f.setSize(200,50);
}
}
class CheckboxPanel extends JPanel
{
Icon unchecked = new ToggleIcon (false);
Icon checked = new ToggleIcon (true);
public CheckboxPanel() {
// Set the layout for the JPanel
setLayout(new GridLayout(2, 1));
// Create checkbox with its state
// initialized to true
JCheckBox cb1 = new JCheckBox("Choose Me", true);
cb1.setIcon(unchecked);
cb1.setSelectedIcon(checked);
// Create checkbox with its state
// initialized to false
JCheckBox cb2 = new JCheckBox("No Choose Me", false);
cb2.setIcon(unchecked);
cb2.setSelectedIcon(checked);
add(cb1);
add(cb2);
}
class ToggleIcon implements Icon {
boolean state;
public ToggleIcon (boolean s) {
state = s;
}
public void paintIcon (Component c, Graphics g, int x, int y) {
int width = getIconWidth();
int height = getIconHeight();
g.setColor (Color.black);
if (state)
g.fillRect (x, y, width, height);
else
g.drawRect (x, y, width, height);
}
public int getIconWidth() {
return 10;
}
public int getIconHeight() {
return 10;
}
}
}
JRadioButton
- In AWT, radio buttons are checkboxes that belong to the same CheckboxGroup; which ensures that only one checkbox is selected at a time.
- Swing has a separate widget called a JRadioButton.
- Each JRadioButton is added to a ButtonGroup so the group behaves as a set of radio buttons.
- Like CheckboxGroup, ButtonGroup is a functional object that has no visual representation.
JRadioButton Example
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class JRadioButtonDemo
{
public static void main(String[] args)
{
RadioButtonPanel p=new RadioButtonPanel ();
JFrame f=new JFrame("JavaSkool Example");
f.add(p);
f.setVisible(true);
f.setSize(200,100);
}
}
class RadioButtonPanel extends JPanel {
public RadioButtonPanel() {
// Set the layout to a GridLayout
setLayout(new GridLayout(4,1));
// Declare a radio button
JRadioButton radioButton;
// Instantiate a ButtonGroup for functional
// association among radio buttons
ButtonGroup rbg = new ButtonGroup();
// Create a label for the group
JLabel label = new JLabel("Annual Salary: ");
label.setFont(new Font(
"SansSerif", Font.BOLD, 14));
add(label);
// Add a new radio button to the pane
radioButton = new JRadioButton("$40,000");
add (radioButton);
// set key accelerator
radioButton.setMnemonic (KeyEvent.VK_4);
// Add the button to the ButtonGroup
rbg.add (radioButton);
// Set this radio button to be the default
radioButton.setSelected(true);
// Set up two more radio buttons
radioButton = new JRadioButton("$60,000");
radioButton.setMnemonic (KeyEvent.VK_6);
add (radioButton);
rbg.add (radioButton);
radioButton = new JRadioButton("$70,000");
radioButton.setMnemonic (KeyEvent.VK_7);
add (radioButton);
rbg.add (radioButton);
}
}
JToggleButton
The JToggleButton class is the parent to both JCheckBox and JRadioButton. It doesn’t have an AWT equivalent. The JToggleButton works like a Button that stays pressed in when toggled on. When a JToggleButton is toggled off, you cannot tell it from a regular Button or JButton class.
JToggleButton Example
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class JToggleButtonDemo
{
public static void main(String[] args)
{
ToggleButtonPanel p=new ToggleButtonPanel ();
JFrame f=new JFrame("JavaSkool Example");
f.add(p);
f.setVisible(true);
f.setSize(200,100);
}
}
class ToggleButtonPanel extends JPanel {
public ToggleButtonPanel() {
// Set the layout to a GridLayout
setLayout(new GridLayout(4,1, 10, 10));
add (new JToggleButton ("Fe"));
add (new JToggleButton ("Fi"));
add (new JToggleButton ("Fo"));
add (new JToggleButton ("Fum"));
}
}
JScrollPane
- Like the AWT 1.1 ScrollPane, JScrollPane handles automatic horizontal and vertical scrolling of content. It lays out components using a ScrollPaneLayout. The key thing to know when using a JScrollPane is that Swing provides a JViewport for adding the object to scroll.
- To get a handle to the viewport, JScrollPane has a getViewport() method. Then, to add a component to the viewport, the JViewport class has an add method.
JViewport vport = someScrollPane.getViewport();
vport.add(someComponent);
Or, more commonly, the two lines are combined:
someScrollPane.getViewport().add(someComponent);
Another option is to provide the component to scroll to the constructor:
JScrollPane pane = new JScrollPane(someComponent);
JScrollPane Example
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class JScrollPaneDemo
{
public static void main(String[] args)
{
ScrollPanel p=new ScrollPanel ();
JFrame f=new JFrame("JavaSkool Example");
f.getContentPane().add(p);
f.setVisible(true);
f.setSize(400,300);
}
}
class ScrollPanel extends JPanel {
public ScrollPanel() {
setLayout(new BorderLayout());
Icon bigTiger = new ImageIcon("banner1.jpg");
JLabel tigerLabel = new JLabel(bigTiger);
JScrollPane scrollPane =
new JScrollPane(tigerLabel);
add(scrollPane, BorderLayout.CENTER);
}
}
Viewports
- The JViewport offers a view into a much larger area then can be seen without it.
- It can be either used within the JScrollPane component or as a standalone widget, where you control all the scrolling functionality yourself.
- Normally, you wouldn’t want to do all the scrolling functionality yourself, but the capability is available. (Besides JScrollPane, JViewport is used internally within the Swing text components to handle scrolling of text.)
JTextComponents
JTextComponent is a generalized text class that contains all the features you would expect from a simple editor. Some of its methods include:
- copy()
- cut()
- paste()
- getSelectedText()
- setSelectionStart()
- setSelectionEnd()
- selectAll()
- replaceSelection()
- getText()
- setText()
- setEditable()
- setCaretPosition()
There are three basic subclasses of JTextComponent:
- JtextField
- JtextArea
- JEditorPane
JPasswordField and JTextPane are sub-subclasses that are also of interest.
If you want your users to be able to see content that exceeds the screen display area, you must place the component inside of a JScrollPane to support scrolling to the extra content.
JTextField & JTextArea
Other than having to add a JTextArea to a JScrollPane for scrolling, JTextField and JTextArea behave very similarly to their AWT counterparts: java.awt.TextField and java.awt.TextArea:
JTextPane Example
// Instantiate a new TextField
JTextField tf = new JTextField();
// Instantiate a new TextArea
JTextArea ta = new JTextArea();
// Initialize the text of each
tf.setText("TextField");
ta.setText("JTextArea\n Allows Multiple Lines");
add(tf);
add(new JScrollPane(ta));
The JTextField also supports setting of text justification with setHorizontalAlignment(). The three available settings are LEFT, CENTER, and RIGHT, where LEFT is the default.
JTextPane
JTextPane is a full-featured text editor that supports formatted text, word wrap, and image display. It uses a linked list of objects that implement the Style interface to specify formatting and supplies some convenience methods for formatting text. A more detailed discussion of JTextPane usage, and the javax.swing.text package, is included in Part II of this course.
JTextPane Example
JTextPane tp = new JTextPane();
MutableAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setFontFamily(attr, "Serif");
StyleConstants.setFontSize(attr, 18);
StyleConstants.setBold(attr, true);
tp.setCharacterAttributes(attr, false);
add(new JScrollPane(tp));
JTextField Example
public class TextPanel extends JPanel {
public TextPanel() {
// Set the layout to a BorderLayout
setLayout(new BorderLayout());
// Create the three basic text components
JTextField textField = new JTextField();
JTextArea textArea = new JTextArea();
JTextPane textPane = new JTextPane();
//Set the textpane's font properties
MutableAttributeSet attr =
new SimpleAttributeSet();
StyleConstants.setFontFamily(attr, "Serif");
StyleConstants.setFontSize(attr, 18);
StyleConstants.setBold(attr, true);
textPane.setCharacterAttributes(attr, false);
add(textField, BorderLayout.NORTH);
add(new JScrollPane(textArea),
BorderLayout.CENTER);
add(new JScrollPane(textPane), BorderLayout.SOUTH);
}
}
JPasswordField
- The JPasswordField is a JTextField that refuses to display its contents openly. By default, the mask character is the asterisk (‘*’).
- However, you can change this with the setEchoChar() method.
- Unlike java.awt.TextField, an echo character of (char)0 does not unset the mask.
JPasswordField Example
class PasswordPanel extends JPanel {
PasswordPanel() {
JPasswordField pass1 = new JPasswordField(20);
JPasswordField pass2 = new JPasswordField(20);
pass2.setEchoChar ('?');
add(pass1);
add(pass2);
}
}
JEditorPane
- The JEditorPane class is a specialized JTextComponent for displaying and editing HTML 3.2 tags or some other format like RTF (rich text format), as determined by the input.
- It is not meant to provide a full-fledged browser, but a lightweight HTML viewer, usually for the purpose of displaying help text.
- You either construct the pane with a URL parameter (via a String or URL), or change pages with the setPage() method. For HTML content, links within the HTML page are traversable with the help of a HyperlinkListener.
JEditorPane Example
public class BrowserDemo extends JPanel {
Browser() {
setLayout (new BorderLayout (5, 5));
final JEditorPane jt = new JEditorPane();
final JTextField input =
new JTextField("http://java.sun.com");
// make read-only
jt.setEditable(false);
// follow links
jt.addHyperlinkListener(new HyperlinkListener () {
public void hyperlinkUpdate(
final HyperlinkEvent e) {
if (e.getEventType() ==
HyperlinkEvent.EventType.ACTIVATED) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Save original
Document doc = jt.getDocument();
try {
URL url = e.getURL();
jt.setPage(url);
input.setText (url.toString());
} catch (IOException io) {
JOptionPane.showMessageDialog (
Browser.this, "Can't follow link",
"Invalid Input",
JOptionPane.ERROR_MESSAGE);
jt.setDocument (doc);
}
}
});
}
}
});
JScrollPane pane = new JScrollPane();
pane.setBorder (
BorderFactory.createLoweredBevelBorder());
pane.getViewport().add(jt);
add(pane, BorderLayout.CENTER);
input.addActionListener (new ActionListener() {
public void actionPerformed (ActionEvent e) {
try {
jt.setPage (input.getText());
} catch (IOException ex) {
JOptionPane.showMessageDialog (
Browser.this, "Invalid URL",
"Invalid Input",
JOptionPane.ERROR_MESSAGE);
}
}
});
add (input, BorderLayout.SOUTH);
}
}
To activate the hyperlinks within the JEditorPane, event handling code is provided. Also, if you only want to display HTML, remember to setEditable(false) to make the editor read-only.
JScrollBar
JScrollBar offers a lightweight version of the java.awt.Scrollbar component.
JScrollBar Example
public class ScrollbarPanel extends JPanel {
public ScrollbarPanel() {
setLayout(new BorderLayout());
JScrollBar scrollBar1 = new JScrollBar (
JScrollBar.VERTICAL, 0, 5, 0, 100);
add(scrollBar1, BorderLayout.EAST);
JScrollBar scrollBar2 = new JScrollBar (
JScrollBar.HORIZONTAL, 0, 5, 0, 100);
add(scrollBar2, BorderLayout.SOUTH);
}
}
JSlider
JSlider functions like a JScrollBar; however, it adds the ability to display major and minor tick marks, as well as display a Border around the slider.
JSlider Example1
public class SliderPanel extends JPanel {
public SliderPanel() {
setLayout(new BorderLayout());
JSlider slider1 =
new JSlider (JSlider.VERTICAL, 0, 100, 50);
slider1.setPaintTicks(true);
slider1.setMajorTickSpacing(10);
slider1.setMinorTickSpacing(2);
add(slider1, BorderLayout.EAST);
JSlider slider2 =
new JSlider (JSlider.VERTICAL, 0, 100, 50);
slider2.setPaintTicks(true);
slider2.setMinorTickSpacing(5);
add(slider2, BorderLayout.WEST);
JSlider slider3 =
new JSlider (JSlider.HORIZONTAL, 0, 100, 50);
slider3.setPaintTicks(true);
slider3.setMajorTickSpacing(10);
add(slider3, BorderLayout.SOUTH);
JSlider slider4 =
new JSlider (JSlider.HORIZONTAL, 0, 100, 50);
slider4.setBorder(
BorderFactory.createLineBorder(Color.blue));
add(slider4, BorderLayout.NORTH);
}
}
In addition to plain tick marks, with JSlider you can place labels along the axis as either a serious of numbers or components. For numeric labels, by just calling setPaintLabels (true), the slider will generate and use a series of labels based on the major tick spacing. So, if the slider range is 0 to 100 with tick spacing of 10, the slider would then have labels of 0, 10, 20, … 100. On the other hand, if you want to generate the labels yourself, you can provide a Hashtable of labels. The hashtable key would be the Integer value of the position. The hashtable value would be a Component to use for display of the label.
The following demonstrates both:
JSlider Example2
public class SliderPanel2 extends JPanel {
public SliderPanel2() {
setLayout(new BorderLayout());
JSlider right, bottom;
right = new JSlider(JSlider.VERTICAL, 1, 9, 3);
Hashtable h = new Hashtable();
h.put (new Integer (1), new JLabel("Mercury"));
h.put (new Integer (2), new JLabel("Venus"));
h.put (new Integer (3), new JLabel("Earth"));
h.put (new Integer (4), new JLabel("Mars"));
h.put (new Integer (5), new JLabel("Jupiter"));
h.put (new Integer (6), new JLabel("Saturn"));
h.put (new Integer (7), new JLabel("Uranus"));
h.put (new Integer (8), new JLabel("Neptune"));
h.put (new Integer (9), new JLabel("Pluto"));
right.setLabelTable (h);
right.setPaintLabels (true);
right.setInverted (true);
bottom =
new JSlider(JSlider.HORIZONTAL, 0, 100, 25);
bottom.setMajorTickSpacing (10);
bottom.setPaintLabels (true);
add(right, BorderLayout.EAST);
add(bottom, BorderLayout.SOUTH);
}
}
JProgressBar
The JProgressBar component allows you to display a progress bar to reflect the status of an operation.
The general format of using a JProgressBar is as follows:
Initialize the JProgressBar:
JProgressBar progressBar = new JProgressBar();
progressBar.setMinimum(0);
progressBar.setMaximum(numberSubOperations);
Repeat each time you want to perform an operation:
progressBar.setValue(progressBar.getMinimum());
for (int i = 0; i < numberSubOperations; i++) {
// Perform sub-operation i
// Update bar value in event thread
// Where runner is created outside for loop
SwingUtilities.invokeAndWait(runner);
}
Outside the for-loop, create the Runnable object
Runnable runner = new Runnable() {
public void run() {
int value = progressBar.getValue();
progressBar.setValue(value+1);
}
};
Often, you will want to set up an operation to execute in a thread and have the operation monitored by a progress bar. This allows the user to cancel the operation if it is taking too long. (The ProgressMonitorInputStream class provides this type of behavior for reading input streams.)
To demonstrate JProgressBar, an example follows. The stepping thread simply counts up, displaying the current count in a JTextField. In addition, the bar displays the current value by setting its stringPainted property to true with progressBar.setStringPainted(true).
JProgressBar Example2
public class ProgressBarPanel extends JPanel {
Thread loadThread;
Object lock = new Object();
boolean shouldStop=false;
JTextField progressTextField;
JProgressBar progressBar;
public ProgressBarPanel() {
setLayout(new BorderLayout());
progressTextField = new JTextField();
add(progressTextField, BorderLayout.NORTH);
JPanel bottomPanel = new JPanel();
progressBar = new JProgressBar();
progressBar.setStringPainted(true);
bottomPanel.setLayout(new GridLayout(0,1));
bottomPanel.add(progressBar);
bottomPanel.add(new JLabel("Load Status"));
JPanel buttonPanel = new JPanel();
JButton startButton = new JButton("Start");
buttonPanel.add(startButton);
startButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
startLoading();
}
});
JButton stopButton = new JButton("Stop");
buttonPanel.add(stopButton);
stopButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
stopLoading();
}
});
bottomPanel.add(buttonPanel);
add(bottomPanel, BorderLayout.SOUTH);
}
public void startLoading() {
if(loadThread == null) {
loadThread = new LoadThread();
shouldStop = false;
loadThread.start();
}
}
public void stopLoading() {
synchronized(lock) {
shouldStop = true;
lock.notify();
}
}
class LoadThread extends Thread {
public void run () {
int min = 0;
int max = 100;
progressBar.setValue(min);
progressBar.setMinimum(min);
progressBar.setMaximum(max);
Runnable runner = new Runnable() {
public void run() {
int value = progressBar.getValue();
value++;
progressBar.setValue(value);
progressTextField.setText (""+value);
}
};
for (int i=min;i <=max;i++) {
try {
SwingUtilities.invokeAndWait(runner);
} catch (InvocationTargetException e) {
break;
} catch (InterruptedException e) {
// Ignore Exception
}
synchronized(lock) {
if(shouldStop)
break;
try {
lock.wait(100);
} catch (InterruptedException e) {
// Ignore Exception
}
}
}
loadThread = null;
}
}
}
JComboBox
- The JComboBox works like AWT’s Choice component, but renames some methods and offers an editable option.
- For times when a fixed-list of choices isn’t enough, you can offer a JComboBox with a list of default choices, but still permit the entry of another value.
- The nicest part about this control is that when the user presses the key for the first letter of an entry, it changes the highlighted selection.
- You can enhance this behavior by providing your own KeySelectionManager, a public inner class of JComboBox.
JComboBox Example
public class ComboPanel extends JPanel {
String choices[] = {
"Mercury", "Venus", "Earth",
"Mars", "Jupiter", "Saturn",
"Uranus","Neptune", "Pluto"};
public ComboPanel() {
JComboBox combo1 = new JComboBox();
JComboBox combo2 = new JComboBox();
for (int i=0;i < choices.length;i++) {
combo1.addItem (choices[i]);
combo2.addItem (choices[i]);
}
combo2.setEditable(true);
combo2.setSelectedItem("X");
combo2.setMaximumRowCount(4);
add(combo1);
add(combo2);
}
}
There is more to JComboBox than just a few new methods and editability. Details are later in this course, after the Model/View/Controller (MVC) Architecture has been explained.
JList
- The JList component has both an easy (non-MVC) implementation and a more complicated view.
- For the MVC-view, you’ll see an example later in this course with JComboBox. For now, you’ll see how to display a list of String objects, just like an AWT List component.
- Thankfully, it has gotten much easier. To add a String[] (or Vector) of elements to a JList, just tell the constructor or use the setListData() method.
- There is one major difference between List and JList. JList doesn’t directly support scrolling. You need to place the JList within a JScrollPane object, and let it deal with the scrolling.
JList Example
public class ListPanel extends JPanel {
String label [] = {"Cranberry", "Orange",
"Banana", "Kiwi", "Blueberry",
"Pomegranate", "Apple", "Pear",
"Watermelon", "Raspberry", "Snozberry"
};
public ListPanel() {
setLayout (new BorderLayout());
JList list = new JList(label);
JScrollPane pane = new JScrollPane(list);
add(pane, BorderLayout.CENTER);
}
}
Borders
The javax.swing.border package consists of several objects to draw borders around components.
They all implement the Border interface, which consists of three methods:
- public Insets getBorderInsets(Component c) Defines the drawable area necessary to draw the border
- public boolean isBorderOpaque() Defines if the border area is opaque or transparent
- public void paintBorder (Component c, Graphics g, int x, int y, int width, int height) Defines how to draw the border within the specified area. The routine should only draw into the area requested with getBorderInsets().
The border behavior is defined for JComponent, so all subclasses inherit the behavior.
Swing provides nine borders, and you can create your own if none of them meets your needs:
- AbstractBorder – An abstract class that implements the Border interface, but does nothing
- BevelBorder – A 3D border that may be raised or lowered
- CompoundBorder – A border that can nest multiple borders
- EmptyBorder – A border where you specify the reserved space for an undrawn border
- EtchedBorder – A border that appears as a groove, instead of raised or lowered
- LineBorder – A border for single color borders, with arbitrary thickness
- MatteBorder – A border that permits tiling of an icon or color
- SoftBevelBorder – A 3D border with softened corners
- TitledBorder – A border that permits title strings in arbitrary locations
You can create a border object directly from the appropriate class constructor or ask a BorderFactory to create the border for you, with methods like createBevelBorder(type) and createTitledBorder(“TItle”).
When using BorderFactory, multiple requests to create the same border return the same object.
Borders Example
public class BorderPanel extends JPanel {
class MyBorder implements Border {
Color color;
public MyBorder (Color c) {
color = c;
}
public void paintBorder (Component c, Graphics g,
int x, int y, int width, int height) {
Insets insets = getBorderInsets(c);
g.setColor (color);
g.fillRect (x, y, 2, height);
g.fillRect (x, y, width, 2);
g.setColor (color.darker());
g.fillRect (x+width-insets.right, y, 2, height);
g.fillRect (x, y+height-insets.bottom, width, 2);
}
public boolean isBorderOpaque() {
return false;
}
public Insets getBorderInsets(Component c) {
return new Insets (2, 2, 2, 2);
}
}
public BorderPanel() {
setLayout (new GridLayout (4, 3, 5, 5));
JButton b = new JButton("Empty");
b.setBorder (new EmptyBorder (1,1,1,1));
add(b);
b = new JButton ("Etched");
b.setBorder (new EtchedBorder ());
add(b);
b = new JButton ("ColorizedEtched");
b.setBorder (new EtchedBorder (Color.red,
Color.green));
add(b);
b = new JButton ("Titled/Line");
b.setBorder(new TitledBorder (
new TitledBorder(
LineBorder.createGrayLineBorder(),
"Hello"),
"World",
TitledBorder.RIGHT,
TitledBorder.BOTTOM));
add(b);
b = new JButton ("Bevel Up");
b.setBorder(new BevelBorder(BevelBorder.RAISED));
add(b);
b = new JButton ("Bevel Down");
b.setBorder(new BevelBorder(BevelBorder.LOWERED));
add(b);
b = new JButton ("Soft Bevel Up");
b.setBorder(
new SoftBevelBorder(SoftBevelBorder.RAISED));
add(b);
b = new JButton ("Soft Bevel Down");
b.setBorder(
new SoftBevelBorder(SoftBevelBorder.LOWERED));
add(b);
b = new JButton ("Matte");
b.setBorder(
new MatteBorder(5, 10, 5, 10, Color.red));
add(b);
b = new JButton ("Matte Icon");
Icon icon = new ImageIcon ("SmallTiger.gif");
b.setBorder(new MatteBorder(10, 10, 10, 10, icon));
add(b);
b = new JButton ("ColorizedBezel");
b.setBorder(new BevelBorder(BevelBorder.RAISED,
Color.red, Color.pink));
add(b);
b = new JButton ("My/Compound");
b.setBorder(new CompoundBorder(
new MyBorder(Color.red),
new CompoundBorder (new MyBorder(Color.green),
new MyBorder(Color.blue))));
add(b);
}
}
You can change the border of any JComponent object with the setBorder() method.
Menus
The menuing model used in Swing is nearly identical to that used in AWT.
There are three key exceptions:
- The menu classes (JMenuItem, JCheckBoxMenuItem, JMenu, and JMenuBar) are all subclasses of JComponent. They are not off in their own independent class hierarchy. As a result of this, you can place a JMenuBar within any Container, including Applet. [The JApplet class has a setJMenuBar() method to add a JMenuBar.]
- There is a new menu class, JRadioButtonMenuItem, to provide a set of mutually exclusive checkboxes on a menu, when placed within a ButtonGroup.
- Also, you can associate an Icon object with any JMenuItem.
Menus Example
public class MenuTester extends JFrame implements ActionListener {
public void actionPerformed (ActionEvent e) {
System.out.println (e.getActionCommand());
}
public MenuTester() {
super ("Menu Example");
JMenuBar jmb = new JMenuBar();
JMenu file = new JMenu ("File");
JMenuItem item;
file.add (item = new JMenuItem ("New"));
item.addActionListener (this);
file.add (item = new JMenuItem ("Open"));
item.addActionListener (this);
file.addSeparator();
file.add (item = new JMenuItem ("Close"));
item.addActionListener (this);
jmb.add (file);
JMenu edit = new JMenu ("Edit");
edit.add (item = new JMenuItem ("Copy"));
item.addActionListener (this);
Icon tigerIcon = new ImageIcon("SmallTiger.gif");
edit.add (item =
new JMenuItem ("Woods", tigerIcon));
item.setHorizontalTextPosition (JMenuItem.LEFT);
item.addActionListener (this);
edit.add (item =
new JMenuItem ("Woods", tigerIcon));
item.addActionListener (this);
jmb.add (edit);
JMenu choice = new JMenu ("Choices");
JCheckBoxMenuItem check =
new JCheckBoxMenuItem ("Toggle");
check.addActionListener (this);
choice.add (check);
ButtonGroup rbg = new ButtonGroup();
JRadioButtonMenuItem rad =
new JRadioButtonMenuItem ("Choice 1");
choice.add (rad);
rbg.add (rad);
rad.addActionListener (this);
rad = new JRadioButtonMenuItem ("Choice 2");
choice.add (rad);
rbg.add (rad);
rad.addActionListener (this);
rad = new JRadioButtonMenuItem ("Choice 3");
choice.add (rad);
rbg.add (rad);
rad.addActionListener (this);
jmb.add (choice);
setJMenuBar (jmb);
}
}
JSeparator
- The JSeparator object is the menu separator control.
- The image below shows the separator under the File menu from the example above.
Because Swing menu objects are truly components, you can use JSeparator outside of menus, too. However, normally you just add them to a JMenu with addSeparator().
JPopupMenu
- The JPopupMenu component allows you to associate context-sensitive menus with any JComponent.
- They work similarly to the AWT PopupMenu class, with an addSeparator() method to add a separator bar.
JPopupMenu Example
public class PopupPanel extends JPanel {
JPopupMenu popup = new JPopupMenu ();
public PopupPanel() {
JMenuItem item;
popup.add (item = new JMenuItem ("Cut"));
popup.add (item = new JMenuItem ("Copy"));
popup.add (item = new JMenuItem ("Paste"));
popup.addSeparator();
popup.add (item = new JMenuItem ("Select All"));
popup.setInvoker (this);
addMouseListener (new MouseAdapter() {
public void mousePressed (MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show (e.getComponent(),
e.getX(), e.getY());
}
}
public void mouseReleased (MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show (e.getComponent(),
e.getX(), e.getY());
}
}
});
}
}
JFrame and Windows
- The Window class hierarchy is a little different when the Swing window classes are added.
- As the diagram shows, they all subclass Window, not JComponent. This means they are not lightweight, have a peer, and cannot be transparent.
- The JFrame class is the replacement for AWT’s Frame class. In addition to the ability to add a java.awt.MenuBar via setMenuBar(), you can add a JMenuBar to a JFrame via setJMenuBar().
- The other difference of the JFrame class is shared with the JWindow and JDialog classes. No longer do you just add() components to each directly or setLayout() to change the LayoutManager. Now, you must get what’s called a content pane, then add components to that or change its layout.
JFrame and Windows Example
public class FrameTester {
public static void main (String args[]) {
JFrame f = new JFrame ("JFrame Example");
Container c = f.getContentPane();
c.setLayout (new FlowLayout());
for (int i = 0; i < 5; i++) {
c.add (new JButton ("No"));
c.add (new Button ("Batter"));
}
c.add (new JLabel ("Swing"));
f.setSize (300, 200);
f.show();
}
}
The reason you have to get a content pane is because the inside of a window is now composed of a JRootPane, which no longer shields you from the inner workings of the Window, as AWT did.
One other difference between JFrame and Frame is JFrame has a property that defines the default close operation. With Frame, nothing happens, by default, if you try to close the frame. On the other hand, JFrame will hide itself when you try to close it.
The setDefaultCloseOperation() method lets you define three operations that can happen when the user tries to close a JFrame:
- DO_NOTHING_ON_CLOSE: The AWT Frame behavior
- HIDE_ON_CLOSE: The default behavior. When user tries to close the window, the window will be hidden. You can then setVisible(true) to reshow it.
- DISPOSE_ON_CLOSE: When user tries to close window, it will be disposed.
Both HIDE_ON_CLOSE and DISPOSE_ON_CLOSE perform their operations last, in case an event listener needs to use the information from the closing event.
JRootPane
A JRootPane is a container that consists of two objects, a glass pane and a layered pane. The glass pane is initially invisible, so all you see is the layered pane. The layered pane also consists of two objects, an optional menu bar and a content pane. You work with the content pane just like you would the inside of a Window, Dialog, or Frame in AWT. The way the glass pane works is if you place a component in it, this component will always display in front of the content pane. This allows things like popup menus and tool tip text to work properly. The layering effect is done with the help of the new JLayeredPane component, explained next.
Normally, the only difference in coding is changing all lines like:
aFrame.setLayout (new FlowLayout());
aFrame.add(aComponent);
to new lines accessing the content pane:
aFrame.getContentPane().setLayout (new FlowLayout());
aFrame.getContentPane().add(aComponent);
The rest of the panes are accessed with similar methods, though are rarely accessed directly. The layout management of all these panes is done through a custom layout manager.
Container getContentPane();
setContentPane (Container);
Component getGlassPane();
setGlassPane (Component);
JLayeredPane getLayeredPane();
setLayeredPane (JLayeredPane);
JMenuBar getMenuBar();
setMenuBar (JMenuBar);
JLayeredPane
The JLayeredPane container keeps its children in layers to define an order to paint its components. When you add a component to the pane, you specify which layer you want it in:
layeredPane.add (component, new Integer(5));
The default layer is the value JLayeredPane.DEFAULT_LAYER. You can add or subtract values from this value to have things appear above or below, layerwise. The LayoutManager of the pane determines what happens with the layers. Using FlowLayout or GridLayout as the layout only reorders the components as they are added; they will not be drawn on top of each other. For an example of actually drawing overlaid components, see the examples subdirectory that comes with the Swing release.
Swing in Applets
For applets to properly handle the Swing component set, your applets need to subclass JApplet instead of Applet. JApplet is a special subclass of Applet that adds support for JMenuBar and handles the painting support required by Swing child components (along with any other necessary tasks like accessibility support). Also, like JFrame, JApplet has a JContentPane to add components into, instead of directly to the applet. Another difference is the default LayoutManager: in JApplet it is BorderLayout, while in Applet it has always been FlowLayout.
Swing in Applets Example
public class AppTester extends JApplet {
public void init () {
Container c = getContentPane();
JButton jb = new JButton ("Default");
c.add (jb, BorderLayout.WEST);
jb = new JButton ("LayoutManager");
c.add (jb, BorderLayout.CENTER);
jb = new JButton ("is");
c.add (jb, BorderLayout.EAST);
jb = new JButton ("BorderLayout: " +
(c.getLayout() instanceof BorderLayout));
c.add (jb, BorderLayout.SOUTH);
}
}
The LayoutManager is actually a custom subclass of BorderLayout. This subclassing ensures that when a component with no constraints is added, the subclass maps the component to the CENTER area.
Tooltips
A tooltip is a context-sensitive text string that is displayed in a popup window when the mouse rests over a particular object on the screen. Swing provides the JToolTip class to support this; however, you will rarely use it directly. To create a tooltip, you only need to call the setToolTipText() method of JComponent.
Tooltips Example
public class TooltipPanel extends JPanel {
public TooltipPanel() {
JButton myButton = new JButton("Hello");
myButton.setToolTipText ("World");
add(myButton);
}
}
Toolbars
- The JToolBar control offers a container that displays its components in a toolbar fashion, across or down, in one row or column, depending upon the area of the screen it is placed in.
- Certain user-interface models permit floatable toolbars; the default user-interface is one that supports floating.
- In order to disable the floatable capability, just call the setFloatable() method.
- It is possible that a particular user interface may ignore this setting.
- Disabling floating
aToolBar.setFloatable (false);
When JToolBar is considered floatable, this means a user can drag it to another area of the screen, or place it in a window external from the original container. - To demonstrate a JToolBar, take a look at the following example. As it demonstrates, there are no restrictions on what components appear within the toolbar.
- However, it works best if they are all the same type and size.
Toolbars Example
public class ToolbarPanel extends JPanel {
ToolbarPanel() {
setLayout (new BorderLayout());
JToolBar toolbar = new JToolBar();
JButton myButton = new JButton("Hello");
toolbar.add(myButton);
Icon tigerIcon = new ImageIcon("SmallTiger.gif");
myButton = new JButton(tigerIcon);
toolbar.add(myButton);
toolbar.addSeparator();
toolbar.add (new Checkbox ("Not"));
add (toolbar, BorderLayout.NORTH);
toolbar = new JToolBar();
Icon icon = new AnOvalIcon(Color.red);
myButton = new JButton(icon);
toolbar.add(myButton);
icon = new AnOvalIcon(Color.blue);
myButton = new JButton(icon);
toolbar.add(myButton);
icon = new AnOvalIcon(Color.green);
myButton = new JButton(icon);
toolbar.add(myButton);
toolbar.addSeparator();
icon = new AnOvalIcon(Color.magenta);
myButton = new JButton(icon);
toolbar.add(myButton);
add (toolbar, BorderLayout.SOUTH);
}
class AnOvalIcon implements Icon {
Color color;
public AnOvalIcon (Color c) {
color = c;
}
public void paintIcon (Component c, Graphics g, int x, int y) {
g.setColor(color);
g.fillOval (x, y, getIconWidth(), getIconHeight());
}
public int getIconWidth() {
return 20;
}
public int getIconHeight() {
return 10;
}
}
}
After dragging around the toolbar, the user may just leave it looking a little different than you originally planned:
JTabbedPane
- The JTabbedPane component offers a tabbed control for quick accessibility to multiple panels.
- If you ever tried to use CardLayout in JDK 1.0/1.1, you’ll appreciate this: JTabbedPane adds the necessary support for changing from one card to the next.
- After creating the control, you add cards to it with the addTab() method.
- There are three forms for the addTab() method. One offers a quick way to associate a JToolTip to a tab, while the others only permit text, an Icon, or both.
- Any Component subclass can be the object added to each card.
-
- addTab(String title, Component component) – Create new tab with title as tab label and component shown within tab when selected.
- addTab(String title, Icon icon, Component component) – Adds an options icon to be associated with the title for the tab. Either may be null.
- addTab(String title, Icon icon, Component component, String tip) – Adds tip as the tooltip for the tab.
JTabbedPane Example
public class TabbedPanel extends JPanel {
String tabs[] = {"One", "Two", "Three", "Four"};
public JTabbedPane tabbedPane = new JTabbedPane();
public TabbedPanel() {
setLayout (new BorderLayout());
for (int i=0;i <tabs.length;i++)
tabbedPane.addTab (tabs[i], null,
createPane (tabs[i]));
tabbedPane.setSelectedIndex(0);
add (tabbedPane, BorderLayout.CENTER);
}
JPanel createPane(String s) {
JPanel p = new JPanel();
p.add(new JLabel(s));
return p;
}
}
JSplitPane
- The JSplitPane control offers user-controlled resizing of two components within a container.
- You can place a JSplitPane within a JSplitPane for control of more then two components, and, you can control whether the splitting happens vertically or horizontally.
- The setContinuousLayout property causes each pane to be updated continuously as the splitter is dragged, when set to true.
- You can move the divider programmatically by setting the dividerLocation property to a floating point value between 0.0 and 1.0 to indicate a percentage of the screen or to an integer value for an absolute position.
- The following screenshots demonstrate a JSplitPane between a JTree and a JList. (Note that the scrollbars in the pictures are there because the components are included in a JScrollPane; it is not a result of the JSplitPane.
- The arrows on the splitter bar are obtained by setting the oneTouchExpandable property of the JSplitPane to true. Pressing them will fully push the splitter in the direction of the arrow, or return it to its previous position.
- Note that the splitter bar will not move past the minimumSize of either component if it can avoid it. In many cases it is desirable to call the following:
- comp.setMinimumSize(new Dimension(0,0)); on each component to allow full movement of the splitter bar.
JSplitPane Example
public class JSplitPanel extends JPanel {
public JSplitPanel() {
setLayout(new BorderLayout());
JTree tree = new JTree();
String[] items = {"a", "two", "three",
"four", "five", "six", "seven"};
JList list = new JList(items);
JScrollPane left = new JScrollPane(tree);
JScrollPane right = new JScrollPane(list);
left.setMinimumSize(new Dimension(0,0));
right.setMinimumSize(new Dimension(0,0));
JSplitPane pane = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT, left, right);
pane.setDividerLocation(0.5);
pane.setOneTouchExpandable(true);
add(pane, BorderLayout.CENTER);
}
}
Recent Comments