Icons are under no obligation to paint themselves the same
way every time they are displayed. It’s perfectly reasonable (and often
quite useful) to have an icon that uses some sort of state information
to determine how to display itself. In the next example, we create two
sliders (JSlider
is explained in
detail in Chapter 6) that can be
used to change the width and height of a dynamic icon:
// DynamicIconExample.java // import javax.swing.*; import javax.swing.event.*; import java.awt.*; // Example of an icon that changes form. public class DynamicIconExample { public static void main(String[] args) { // Create a couple of sliders to control the icon size. final JSlider width = new JSlider(JSlider.HORIZONTAL, 1, 150, 75); final JSlider height = new JSlider(JSlider.VERTICAL, 1, 150, 75); // A little icon class that uses the current slider values class DynamicIcon implements Icon { public int getIconWidth( ) { return width.getValue( ); } public int getIconHeight( ) { return height.getValue( ); } public void paintIcon(Component c, Graphics g, int x, int y) { g.fill3DRect(x, y, getIconWidth( ), getIconHeight( ), true); } }; Icon icon = new DynamicIcon( ); final JLabel dynamicLabel = new JLabel(icon); // A listener to repaint the icon when sliders are adjusted class Updater implements ChangeListener { public void stateChanged(ChangeEvent ev) { dynamicLabel.repaint( ); } }; Updater updater = new Updater( ); width.addChangeListener(updater); height.addChangeListener(updater); // Lay it all out. JFrame f = new JFrame( ); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container c = f.getContentPane( ); c.setLayout(new BorderLayout( )); c.add(width, BorderLayout.NORTH); c.add(height, BorderLayout.WEST); c.add(dynamicLabel, BorderLayout.CENTER); f.setSize(210,210); f.setVisible(true); } }
Figure 4-8 shows the dynamic icon in its initial state, and then after we’ve moved the sliders around a bit.
The important thing to notice is that the DynamicIcon
class does not actually store any
information. In this case, we made the Icon
class an inner class, giving it direct
access to the sliders. Whenever the icon is told to paint itself, it
gets its width and height from the values of the sliders. You could also
choose to make your Icon
class an
event listener and have it update itself according to changes in certain
events. The options here are wide open.
No matter how your icon gets its data, you need to make sure that
any time you want to change the way it looks, you trigger a repaint of
the icon. In this example, we’ve done this by listening to change events
from the sliders and calling repaint(
)
on the label that’s holding the icon whenever one of the
sliders changes.
Get Java Swing, 2nd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.