Even the simplest Swing components have capabilities far beyond what the AWT components offer:
Another interesting feature is that Swing components
with state use models to keep the state. A JSlider, for
instance, uses a BoundedRangeModel object
to hold its current value and range of legal values. Models are set
up automatically, so you don't have to deal
with them unless you want to take advantage of the power they can
give you.
If you're used to using AWT components, you need to be aware of a few gotchas when using Swing components:
When a Swing GUI needs to paint itself -- whether for the first time, in response to becoming unhidden, or because it needs to reflect a change in the program's state -- it starts with the highest component that needs to be repainted and works its way down the containment hierarchy. This process is orchestrated by the AWT painting system, and made more efficient and smooth by the Swing repaint manager and double-buffering code.
Swing components generally repaint themselves whenever necessary. When you invoke the setText method on a component, for example, the component should automatically repaint itself and, if appropriate, resize itself. If it doesn't, it's a bug. The workaround is to invoke the repaint method on the component to request that the component be scheduled for painting. If the component's size or position needs to change but doesn't do so automatically, you should invoke revalidate upon the component before invoking repaint.
Like event-handling code, painting code executes on the event-dispatching thread. While an event is being handled, no painting will occur. Similarly, if a painting operation takes a long time, no events will be handled during that time.
For smoothness, Swing painting is double-buffered
by default -- performed to an offscreen buffer and then flushed to the
screen once finished. It might slightly help performance if you make a
Swing component opaque, so that the Swing painting system can know
not to paint anything behind the component. To make a Swing component opaque,
invoke setOpaque(true) on the component.
The Single-Thread Rule : Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread.
Realized: A Swing component that's a top-level window
is realized by having one of these methods invoked on it:
setVisible(true), show, or pack. Once a window is realized,
all the components that it contains are realized.
Another way to realize a component is to add it to a container that's
already realized.
Two JComponent methods are safe to call from any thread: repaint
and revalidate.
These methods queue requests to be executed on the event-dispatching
thread.
Also, it's always safe to call the addListenerTypeListener and removeListenerTypeListener
methods.
The add/remove operations have no effect on an event dispatch that's
under way.
The SwingUtilities class provides two methods to help you run code in the event-dispatching thread:
invokeLater
Requests that
some code be executed in the event-dispatching thread. This method returns
immediately,
without waiting
for the code to execute.
invokeAndWait
Acts like invokeLater,
except that this method waits for the code to execute. As a rule, you should
use
invokeLater
rather than this method.
JComponent : All non-top level swing components starting with
J are subclass of JComponent class. It provides features like tooltip text,
border, configurable L&F, Double Buffering etc.
Icons : Swing components such as JButton and JLabel can have
images represented by Icon Objects.
Actions : If you want multiple objects to share state and data
information during action event, use Action objects.
Pluggable Look and Feel : A Single program can have any one
of several L&F. It can be chosen by the end user or set programmatically
set.
Support Assistive Technologies: Swing API comes with in built
support for Assistive Technologies.
Separate Data and State Models: All noncontainer Swing Components
have a underlying model. JButton has a ButtonModel which
stores information like - Keyboard Mnemonic, enabled state or not, selected,
pressed and so.
Some Swing Component can have more than one underlying models. For
example JList has ListModel which contains the List's contents
and ListSelectionModel which contains information about its list
selection.
Working with models directly is more efficient and faster.
The JComponent class extends java.awt.Container class. There are some classes like Box.Filler which are not top-level container and that do not subclass JComponent.
Important methods include : setToolTipText, setBorder, registerKeyboardAction(specify a KeyStroke Object), putClientProperty, getClientProperty (properties for use by Layout Managers), setPreferredSize, setMinimumSize, setMaximumSize, setAlignmentX, setAlignmentY (setter methods: Component class provides getter methods), setOpaque, isOpaque etc
Each top-level container has a containment hierarchy of its own.
Top-Level container has a content-pane that contains all the visible components of the top-level container. It is an intermediate container that inherits from JComponent class with a BorderLayout layout Manager. getContentPane returns a Container object and not a JComponent object. Generally an opaque JComponent , such as JPanel, is constructed to contain all the visible components and set as the content pane with setContentPane.
In theory all top-level container can have a JMenuBar. But generally a JFrame or a JApplet has JMenuBar. Use setJMenuBar.
All top-level container has a RootPane that supports the content pane,
menubar, Layered pane and Glass Pane.
It is used to intercept mouse click or paint over multiple components.
The layered pane directly contains the menu bar and content pane, and enables Z-ordering of other components you might add. The glass pane is often used to intercept input events occurring over the top-level container, and can also be used to paint over multiple components.
JFrame extends from java.awt.Frame.
By default, when the user closes a frame onscreen,
the frame is hidden. Although invisible, the frame still exists and
the program can make it visible again. If
you want different behavior, then you need to either register a window
listener that handles window-closing events,
or you need to specify default close behavior using the
setDefaultCloseOperation method. You
can even do both.
The argument to setDefaultCloseOperation must
be one of the following values, which are defined in the
WindowConstants interface (which JFrame
implements):
API: createRootPane, setRootPane, getRootPane, getGlassPane, setGlassPane, setLayeredPane, getLayeredPane, setContentPane, getContentPane, setJMenuBar, getJMenuBar, setDefaultCloseOperation etc
Extends the java.awt.Dialog class.
Every dialog is dependent on a frame. When
that frame is destroyed, so are its dependent dialogs. When the
frame is iconified, its dependent dialogs
disappear from the screen. When the frame is deiconified, its dependent
dialogs return to the screen. The AWT automatically
provides this behavior.
A dialog can be modal. When a modal dialog
is visible, it blocks user input to all other windows in the program.
The dialogs that JOptionPane
provides are modal. To create a non-modal dialog, you must use the JDialog
class directly.
JOptionPane class
It is a container that automatically creates a JDialog and put itself to the contentpane of the JDialog. It is Modal.
JOptionPane's icon support lets you easily
specify which icon the dialog displays. You can use a custom icon, no
icon at all, or any one of four standard JOptionPane
icons (question, information, warning, and error). Each look
and feel has its own versions of the four
standard icons.
JOptionPane API:
Method | Purpose |
int showMessageDialog(Component, Object)
int showMessageDialog(Component, Object, String, int) int showMessageDialog(Component, Object, String, int, Icon) |
Show a one-button, modal dialog that gives the user some information. The arguments specify (in order) the parent component, message, title, message type, and icon for the dialog. |
int showOptionDialog(Component, Object, String, int, int,Icon, Object[], Object | Show a customized modal dialog. The arguments specify (in order) the parent component, message, title, option type, message type, icon, options, and initial value for the dialog. |
int showConfirmDialog(Component, Object)
int showConfirmDialog(Component, Object, String, int) int showConfirmDialog(Component, Object, String, int, int) int showConfirmDialog(Component, Object, String, int, int, Icon) |
A modal dialog that ask the user a question. The arguments specify (in order) the parent component, message, title, message type, and icon for the dialog. |
String showInputDialog(Object)
String showInputDialog(Component, Object) String showInputDialog(Component, Object, String, int) String showInputDialog(Component, Object, String, int, Icon, Object[], Object) |
Show a modal dialog that prompts the user for input. The single-argument version specifies just the message, with the parent component assumed to be null. The arguments for the other versions specify (in order) the parent component, message, title, message type, icon, options, and initial value for the dialog |
Description of arguments in the above methods:
Component parentComponent
The first argument
to each showXxxDialog method is always the parent component, which must
be a
frame, a component
inside a frame, or null. If you specify a frame, then the dialog will appear
over the
center of the
frame, and depend on that frame. If you specify a component inside a frame,
then the dialog
will appear
over the center of that component, and depend on that component's frame.
If you specify null,
then the look
and feel picks an appropriate position for the dialog -- generally the
center of the screen, and
the dialog doesn't
depend on any visible frame.
The JOptionPane
constructors do not include this argument. Instead, you specify the parent
frame when
you create the
JDialog that contains the JOptionPane, and you use the JDialog
setLocationRelativeTo
method to set the dialog's position.
Object message
This required
argument specifies what the dialog should display in its main area. Generally,
you specify a
string, which
results the dialog displaying a label with the specified text. You can
split the message over
several lines
by putting newline (\n) characters inside the message string. For example:
"Complete the sentence:\n \"Green eggs and...\""
String title
The title of
the dialog.
int optionType
Specifies the
set of buttons that appear at the bottom of the dialog. Choose from one
of the following
standard sets:
DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION,
OK_CANCEL_OPTION.
int messageType
This argument
determines the icon displayed in the dialog. Choose from one of the following
values:
PLAIN_MESSAGE
(no icon), ERROR_MESSAGE, INFORMATION_MESSAGE,
WARNING_MESSAGE,
QUESTION_MESSAGE.
Icon icon
The icon to
display in the dialog.
Object[] options
Further specifies
the option buttons to appear at the buttom of the dialog. Generally, you
specify an array of
strings for
the buttons. See Customizing Button Text in a Standard Dialog for more
information.
Object initialValue
Specifies the
default value to be selected.
Knowing User's Response:
The showMessageDialog, showConfirmDialog, and showOptionDialog methods return an integer indicating the user's choice. The values for this integer are YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, and CLOSED_OPTION. Except for CLOSED_OPTION, each option corresponds to the button the user pressed. When CLOSED_OPTION is returned, it indicates that the user closed the dialog window explicitly, rather than by choosing a button inside the option pane.
Customized Dialog:
1. Create a JOptionPane like ... new JOptionPane(mesg,optionType, OptionType)
2. Create a JDialog
3. set the JOptionPane of step1 as the contentPane of the JDialog of
step2
4. To override the default behaviour of a JOptionPane getting closed
as the user chooses an option, register a PropertyChageListener to the
JDialog. Get propertyName and handle it according to your requirments.
If the browser is Swing enabled an html file with <APPLET>tag can
be used to run an applet. If the browser does not support swing, java plug-in
must be used and the applet should be specified using <OBJECT> tag ot
<EMBED> tag. There are tools that generates this new tags from <APPLET>
tag.
Intermediate Swing Containers:
DeskTop Pane is a specialized Layered Pane intermediate container that is used to contain JInternalFrame.
JPanel Class
The Layout manager can be specified at instantiation time as an argument
to the constructor or by using the setLayout method.
You can change a scroll pane's client dynamically by calling the setViewportView
method. Note that
JScrollPane has no corresponding getViewportView method, so
you should cache the client object in a
variable if you need to refer to it later.
JScrollPane uses an instance of JViewPort to manage its visible
region. It uses instances of JScrollBar to manage scrolling.
ScrollPane policy
The scroll bar policy of the horizontal and vertical scroll bars can
be specified at creation time or set dynamically:
JScrollPane(Component, vertPolicy, horiPolicy)
JScrollPane(vertPolicy, horiPolicy)
OR
setHorizontalScrollBarPolicy(int)
setVerticalScrollBarPolicy(int)
In above the int values can be one of the following constants defined
in the ScrollPaneConstants Interface:
VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED, VERTICAL_SCROLLBAR_ALWAYS,
HORIZONTAL_SCROLLBAR_ALWAYS, VERTICAL_SCROLLBAR_NEVER, HORIZONTAL_SCROLLBAR_NEVER
Custom Decorations
The area drawn by a scroll pane consists of up to nine parts: the center,
four sides, and four corners. The center is
the only component that is always present in all scroll panes. Besides
scroll bars, the sides can contain column and
row headers. A corner component is visible only if both sides that
intersect at that corner contain visible
components.
API: setColumnHeaderView(Component), setRowHeaderView(Component), setCorner(JScrollPane.XXX_XXX_CORNER, Component)
Scroll-Savvy Client
To customize the way that a client component interacts with its scroll
pane, you can make the component
implement the Scrollable interface. By implementing Scrollable,
a client can specify both the size of the
viewport used to view it and the amount to scroll for clicks on the
different controls on a scroll bar.
The Scrollable interface includes the following methods:
Lists, Tables, textComponents, and trees implements the scrollable interface.
Sizing the Scroll Pane
By default the size of a scroll pane is the preferred size of it nine
components.
If the size of the client is fized then having a scroll pane is redundant.
To get the scroll bars, in such as case, is to set the preferred size of
the scroll pane or its container.
Scroll-savvy clients implements Scrollable interface and provides methods
that the scroll pane uses to determine it scrolling behaviour. Scroll-savvy
class like lists, tables provides methods the programmer can call to set
the values returned by the methods of the Scrollable interface.
Dynamically Changing Client's Size
Step 1. Reset the preferred size of the client
Step 2. revalidate the client
API: setViewportView, setViewportBorder etc
Scrolling methods in other class : setVisibleRowCount (JList, JTree),
setPreferredScrollableViewportSize (JTable) etc.
JSplitPane([orientation],[boolean],[component1,component2])
orientation : JSplitPane.HORIZONTAL_SPLIT, JSplitPane.VERTICAL_SPLIT
boolean : Determines whether the component repaints as the user drags
the split pane.
setOneTouchExpandable, setDividerSize, setDividerLocation, setOrientation,
setLeftComponent, setRightComponent, setTopComponent, setBottomComponent
JTabbedPane([int]) : The int specfies constants from SwingConstants
interface
: TOP, BOTTOM, LEFT, RIGHT
addTab(TabLabelText, [Icon], component,[toolTipText]), setSelectedIndex(int)
-- index starts from 0
It uses BoxLayout as its layout manager and hence can have its components call setAlignmentX, setAlignmentY etc.
API: JToolBar(), add(Component), add(Action), addSeparatot(),
setFloatable(boolean) etc
The internal frame is implemented with platform-independent code and hence has more features than normal frames. It can specify the window decorations for resizing, iconifying, and maximizing. Internal frames cannot be root of a containment hierarchy. It does not generate windows event and generates Internal Frame events. Internal frame supports root pane and hence realizing GUI in internal frame is similar to that of normal frame.
Important rules while using internal frames:
- It is usually contained in a LayeredPane as JDeskTopPane.
- By default the internal frame has 0 size and must be set using pack,
setSize or setBounds
- set the location in within its container using setLocation
or setBounds
- to add components to an internal frame add it to the content
pane of the internal frame
- to allow just outline drawing at the time of dragging use : internalframecontainer.setClientProperty("JDesktopPane.fragMode",
"outline")
API: setJMenuBar, setDefaultCloseOperation, addInternalFrameListener,
moveToFront, moveToBack etc
All containers with root pane supports a JLayeredPane.
There are 2 main classes of Layered Pane : JLayeredPane and its sublcass
JDesktopPane.
A Layered Pane does not have default layout manager. This is because all existing managers lays out components as if all of them are in a single layer.
Depth: The higher the value higher the depth.
Position: The higher the value lower the depth with the same layer.
If there are n components in a layer, the position ranges from 0 to n-1.
-1 is same as n-1. For example when n=3 we have:
API: JLayeredPane(), add(Component,[depthasInteger],[positioninsamelayerasInt]), setLayer(Component, depthasInt, [positionasInt]), setPosition(Component, positionasInt), moveToFront(Component), moveToBack(Component) etc
If in add method depth is not specified it is assumed to be 0. If position
is not specified then it is same n-1.
The setPosition and moveTo.. are methods for the same layer.
The JRootPane uses a JLayeredPane instance:
The description of each of this layers are shown below:
Layer Name | Value | Description |
FRAME_CONTENT_LAYER | new Integer(-30000) | This layer is used to position the frame's content pane and
menu bar. Most programs won't use this. The root pane adds the menu bar and content pane to its layered pane at this depth. |
DEFAULT_LAYER | new Integer(0) | Most components go in this layer. If you don't specify a
component's depth, the layered pane puts it at this depth. |
PALETTE_LAYER | new Integer(100) | This layer is useful for floating toolbars and palettes. |
MODAL_LAYER | new Integer(200) | Modal internal-frame dialogs would belong in this layer. |
POPUP_LAYER | new Integer(300) | Popups go in this layer because they need to appear above
just about everything. |
DRAG_LAYER | new Integer(400) | Move a component to this layer when dragging. Return the
component to its regular layer when dropped. |