Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Magic with Merlin: AWT roundup

Details on changes to sizing, colors, mouse wheel, and input events

John Zukowski (jaz@zukowski.net), President, JZ Ventures, Inc.
Author photo
John Zukowski conducts strategic Java consulting with JZ Ventures, Inc. and serves as the resident guru for a number of jGuru's community-driven Java FAQs. His latest books are Java Collections and Definitive Guide to Swing for Java 2 (2nd ed) from Apress. You can contact John at jaz@zukowski.net.

Summary:  Merlin makes several additions to the AWT library, including the ability to find the space used for screen adornments like the desktop toolbar, capitalizing Color constants, mouse wheel support, and the ability to differentiate between mouse and keyboard keys and locations better. Follow along with John Zukowski as he describes these changes and provides the nitty-gritty details to get you started fast.

View more content in this series

Date:  01 Nov 2001
Level:  Introductory
Also available in:   Japanese

Activity:  5626 views
Comments:  

The Abstract Window Toolkit (AWT) has been upgraded with the new Merlin release. Many of the changes are modest but nonetheless important enough to merit mention. This month, we'll take a look at four new capabilities:

  • The ability to discover space used by screen adornments.
  • The capitalization of constants in the Color class.
  • The support for reacting to mouse wheel events.
  • The ability to differentiate between mouse buttons, keypad keys, and shift keys better.

Getting started

To demonstrate the new AWT features, we'll create a program that sizes the screen to the full size (minus desktop adornments like the toolbar) and uses the new color constants to set the background. You'll be able to change background colors by either rotating the mouse wheel or using the left and right shift keys.

Listing 1 provides the basic shell of the program. Unfortunately, there is still a bug in the mouse wheel support capabilities to be used (see Resources for details). You'll need to add a JButton to a JScrollPane to the frame in order for that to work. Because of that bug, the shell is a little more complex than necessary.


Listing 1. Shell to create frame that is closable
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class AwtTest {

  // See bug 4475240
  static JButton button = new JButton();
  static JScrollPane pane = new JScrollPane(button);

  public static void main(String args[]) {
    JFrame frame = new JFrame("AwtTest");
    // See bug 4475240
    frame.getContentPane().add(button, BorderLayout.CENTER);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.show();
  }
}


Toolkit insets

In a previous column, I mentioned the ability to maximize a Frame with setExtendedState() . If you set the state to Frame.MAXIMIZED_BOTH, your frame is fully maximized. If, however, you don't want the frame maximized, but you do want it sized to fill the user's desktop area, less any desktop adornments, you can now ask for the Insets used by those adornments (see Listing 2). This information is provided by the getScreenInsets() method of Toolkit. If you subtract the insets from the screen size, you have the size your window should be. To position it properly, you'll need to use the top and left insets, too.


Listing 2. Size the screen
  private static void sizeScreen(JFrame frame) {
    Toolkit kit = Toolkit.getDefaultToolkit();
    Dimension screenSize = kit.getScreenSize();
    GraphicsConfiguration config = frame.getGraphicsConfiguration();
    Insets insets = kit.getScreenInsets(config);
    screenSize.width -= (insets.left + insets.right);
    screenSize.height -= (insets.top + insets.bottom);
    frame.setSize(screenSize);
    frame.setLocation(insets.left, insets.top);
  }

Just add a call to sizeScreen() into your main() method.


Color caps

Section 6.8 of the Java Language Specification includes naming conventions for items like packages, methods, fields, and constants. The subsection on constant names (6.8.5) states that constants shouldn't use lowercase letters, but since the beginning, all the color constants in the Color class, like red, green, and blue, have been specified in all lowercase. Merlin sets the record straight and now provides the same constants in all uppercase, too. The old names aren't deprecated, yet, but you can use the newer names with your 1.4 programs.

For the test program, we'll create an array of color constants and a counter to loop through them, then provide a changeBackground() method that loops through them, in one of two directions (see Listing 3).


Listing 3. Change the background color
  private static final Color colors[] = {
    Color.BLACK,
    Color.BLUE,
    Color.CYAN,
    Color.DARK_GRAY,
    Color.GRAY,
    Color.GREEN,
    Color.LIGHT_GRAY,
    Color.MAGENTA,
    Color.ORANGE,
    Color.PINK,
    Color.RED,
    Color.WHITE,
    Color.YELLOW
  };

  static int colorCounter;
  
  private static final int UP = 1;
  private static final int DOWN = 2;

  private static void changeBackground(JFrame frame, int direction) {
    // See bug 4475240
    // w/o bug, change background of getContentPane()
    button.setBackground(colors[colorCounter]);

    // Update counter based on direction
    if (direction == UP) {
      colorCounter++;
    } else {
      --colorCounter;
    }

    // Wrap colors
    if (colorCounter == colors.length) {
      colorCounter = 0;
    } else if (colorCounter < 0) {
      colorCounter = colors.length-1;
    }
  }

Add a call to the changeBackground() method to your main() routine.

The naming conventions were also updated in some other classes, like GridBagLayout, which included several protected methods like AdjustForGravity() that have now been modified to begin with a lowercase letter.


Detecting mouse wheel movement

One feature that Java developers have clamored for since the last century is support for mouse wheel rotation. With the Merlin release, you can now attach a MouseWheelListener to any Component and respond accordingly. Other than the previously mentioned bug, it works nicely. The JScrollPane component even comes with a pre-registered listener, so the pane will scroll when it has focus and the user moves the wheel.

The listener has a single method, mouseWheelMoved(), which gets a MouseWheelEvent argument. From the event, you can find out the amount to scroll with getScrollAmount(), whether it is a unit or block scroll with getScrollType(), the direction and number of wheel rotations with getWheelRotation, and, for convenience, the units to scroll with getUnitsToScroll().

In the test program, we'll attach a wheel listener that has the background color loop through the array of colors based upon the direction, as shown in Listing 4. Documentation states that mouse wheel events propagate up the container hierarchy, but the bug prevents this from happening so you'll need to attach the listener to the button. Be sure to add the listener in the main() method.


Listing 4. Attach wheel listener
  private static void attachMouseWheelListener(final JFrame frame) {
    MouseWheelListener listener = new MouseWheelListener() {
      public void mouseWheelMoved(MouseWheelEvent e) {
        int count = e.getWheelRotation();
        int direction = (Math.abs(count) > 0) ? UP : DOWN;
        changeBackground(frame, direction);
      }
    };
    button.addMouseWheelListener(listener);
  }


Input events

This last feature is larger than you might first think, as the test program uses only a small part of the added capabilities. Basically, Merlin adds the ability to differentiate between different versions of the same key (keypad and regular) and different sequences of keyboard keys and mouse buttons. For instance, previously, there was no way to tell the difference between a shift-click and clicking a different button; both produced the same mouse event. With the help of the following new constants in the InputEvent class, that's all changed:

  • ALT_DOWN_MASK
  • CTRL_DOWN_MASK
  • META_DOWN_MASK
  • SHIFT_DOWN_MASK
  • BUTTON1_DOWN_MASK
  • BUTTON2_DOWN_MASK
  • BUTTON3_DOWN_MASK
  • BUTTON1_CHANGED_MASK
  • BUTTON2_CHANGED_MASK
  • BUTTON3_CHANGED_MASK

If all you want to find out is which button is down, the following methods are of more use:

  • isButton1Down()
  • isButton2Down()
  • isButton3Down()

The MouseEvent also provides a getButton() method to discover which button changed state.

All these methods and constants should make responding to button events easier.

Dfferentiating between different versions of the same key requires changes to the KeyEvent class. You can ask the event for the key location with getKeyLocation(); you get back one of the following constants:

  • KEY_LOCATION_LEFT
  • KEY_LOCATION_NUMPAD
  • KEY_LOCATION_RIGHT
  • KEY_LOCATION_STANDARD
  • KEY_LOCATION_UNKNOWN

By asking where the location of a key is, you can differentiate between keypad and standard keys as well as left and right shift keys.

For the test program, we'll simply have a key listener loop up or down based on whether the left or right shift key is pressed, as shown in Listing 5. We must be sure to check which key is pressed first, then check for location. And, of course, add a call to the routine in the main() method.


Listing 5. Attach key listener
  private static void attachKeyListener(final JFrame frame) {
    KeyListener listener = new KeyAdapter() {
      public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
          int location = e.getKeyLocation();
          int direction = (location == KeyEvent.KEY_LOCATION_LEFT) ? 
            UP : DOWN;
          changeBackground(frame, direction);
        }
      }
    };
    button.addKeyListener(listener);
  }


Complete example

Listing 6 provides a complete example for you to try out all these new capabilities. When the mouse wheel listener bug is fixed, you'll be able to remove the use of the button and scroll pane.


Listing 6. Complete example
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class AwtTest {

  private static final Color colors[] = {
    Color.BLACK,
    Color.BLUE,
    Color.CYAN,
    Color.DARK_GRAY,
    Color.GRAY,
    Color.GREEN,
    Color.LIGHT_GRAY,
    Color.MAGENTA,
    Color.ORANGE,
    Color.PINK,
    Color.RED,
    Color.WHITE,
    Color.YELLOW
  };

  static int colorCounter;

  private static final int UP = 1;
  private static final int DOWN = 2;

  // See bug 4475240
  static JButton button = new JButton();
  static JScrollPane pane = new JScrollPane(button);

  private static void sizeScreen(JFrame frame) {
    Toolkit kit = Toolkit.getDefaultToolkit();
    Dimension screenSize = kit.getScreenSize();
    GraphicsConfiguration config = frame.getGraphicsConfiguration();
    Insets insets = kit.getScreenInsets(config);
    screenSize.width -= (insets.left + insets.right);
    screenSize.height -= (insets.top + insets.bottom);
    frame.setSize(screenSize);
    frame.setLocation(insets.left, insets.top);
  }

  private static void changeBackground(JFrame frame, int direction) {
    // See bug 4475240
    // w/o bug, change background of getContentPane()
    button.setBackground(colors[colorCounter]);

    // Update counter based on direction
    if (direction == UP) {
      colorCounter++;
    } else {
      --colorCounter;
    }

    // Wrap colors
    if (colorCounter == colors.length) {
      colorCounter = 0;
    } else if (colorCounter < 0) {
      colorCounter = colors.length-1;
    }
  }

  private static void attachMouseWheelListener(final JFrame frame) {
    MouseWheelListener listener = new MouseWheelListener() {
      public void mouseWheelMoved(MouseWheelEvent e) {
        int count = e.getWheelRotation();
        int direction = (Math.abs(count) > 0) ? UP : DOWN;
        changeBackground(frame, direction);
      }
    };
    // See bug 4475240
    // w/o bug, add to frame
    button.addMouseWheelListener(listener);
  }

  private static void attachKeyListener(final JFrame frame) {
    KeyListener listener = new KeyAdapter() {
      public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
          int location = e.getKeyLocation();
          int direction = (location == KeyEvent.KEY_LOCATION_LEFT) ? 
            UP : DOWN;
          changeBackground(frame, direction);
        }
      }
    };
    // See bug 4475240
    // w/o bug, add to frame
    button.addKeyListener(listener);
  }

  public static void main(String args[]) {
    JFrame frame = new JFrame("AwtTest");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // See bug 4475240
    frame.getContentPane().add(button, BorderLayout.CENTER);
    sizeScreen(frame);
    changeBackground(frame, UP);
    attachMouseWheelListener(frame);
    attachKeyListener(frame);
    frame.show();
  }
}



Download

NameSizeDownload method
j-mer1106awttest.zip1 KB HTTP

Information about download methods


Resources

About the author

Author photo

John Zukowski conducts strategic Java consulting with JZ Ventures, Inc. and serves as the resident guru for a number of jGuru's community-driven Java FAQs. His latest books are Java Collections and Definitive Guide to Swing for Java 2 (2nd ed) from Apress. You can contact John at jaz@zukowski.net.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=10603
ArticleTitle=Magic with Merlin: AWT roundup
publish-date=11012001
author1-email=jaz@zukowski.net
author1-email-cc=jaloi@us.ibm.com