Skip to main content

Taming Tiger: AWT grows up

Mouse positioning and z-order

John Zukowski (jaz@zukowski.net), President, JZ Ventures, Inc.
Author photo
John Zukowski conducts strategic Java consulting with JZ Ventures, Inc. and is working with SavaJe Technologies to develop a next-generation mobile phone platform. His latest books are The Definitive Guide to Java Swing, Third Edition (Apress, June 2005) and Mastering Java 2, J2SE 1.4 (Sybex, April 2002)

Summary:  The Abstract Window Toolkit is the basis of the Swing component set. Follow along with John Zukowski as he discusses the aspects of AWT that changed with the 5.0 release of the Java™ 2 platform. These include PointerInfo and MouseInfo for recovering pointer position and z-order management for screens with overlaid components.

View more content in this series

Date:  24 May 2005
Level:  Introductory
Activity:  2014 views
Comments:  

When it comes to discussing Java user interfaces, the Swing component set gets all the press. But there's more to GUIs than Swing. Just like with earlier releases of the Java platform, Swing is built on top of the Abstract Window Toolkit (AWT).

What does it mean by "on top of"? Nothing happens in Swing without underlying support in AWT. For instance, the original version of AWT had what is called peered components; when you created an AWT Button component, it created a native component. On a Microsoft Windows machines, it would create a Windows button component, and on a Solaris system, it would create a Motif button. Ten years ago, when the Java language was first introduced, native components seemed like the way to go.

Version 1.1 of the Java platform changed things. It added the ability to create peerless or lightweight components. Prior to these changes, Swing couldn't exist; the way to create a custom component was to subclass Canvas, which created a component native to the platform.

But I digress. This month's tip isn't about the origins of Swing or the Java language, it's about how AWT advanced with the 5.0 release. While Swing is typically the most visible change, it certainly isn't the only one. On to the AWT enhancements.

PointerInfo and MouseInfo

Two new classes added to the Java 5.0 platform are PointerInfo and MouseInfo. These classes help you locate the mouse on the desktop. Starting with the MouseInfo class, you get two static methods:

  • int getNumberOfButtons() tells you how many buttons are on your mouse. Depending on the number of mouse buttons, you may want to configure the available operations differently, as shown in Listing 1:


    Listing 1. Counting mouse buttons
    
    public class Mouse {
      public static void main(String args[]) {
        int count = MouseInfo.getNumberOfButtons();
        System.out.println("Mouse buttons = " + count);
      }
    }
    



  • PointerInfo getPointerInfo() returns a PointerInfo object.

The PointerInfo object returned has its own set of two methods:

  • GraphicsDevice getDevice() reports the device where the mouse is located, the actual GraphicsDevice object. On a system with multiple screens, call this method and get the associated GraphicsDevice object, specific to the mouse location.

  • Point getLocation() gets the physical location of the mouse on screen, as shown in Listing 2:


    Listing 2. Getting mouse position
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Pos {
      public static void main(String args[]) {
        Runnable runnable = new Runnable() {
          public void run() {
            JFrame frame = new JFrame("Mouse Position");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          JLabel label = new JLabel();
            label.setHorizontalAlignment(JLabel.CENTER);
            MouseMotionListener mouseMotionListener = new MouseMotionListener() {
              public void mouseDragged(MouseEvent e) {
                showMousePos(e);
              }
    
              public void mouseMoved(MouseEvent e) {
                showMousePos(e);
              }
    
              private void showMousePos(MouseEvent e) {
                JLabel src = (JLabel)e.getComponent();
                PointerInfo pointerInfo = MouseInfo.getPointerInfo();
                Point point = pointerInfo.getLocation();
                src.setText(point.toString());
              }
            };
            label.addMouseMotionListener(mouseMotionListener);
            frame.add(label, BorderLayout.CENTER);
            frame.setSize(300, 300);
            frame.setVisible(true);
          }
        };
        EventQueue.invokeLater(runnable);
      }
    }
    

Figure 1 shows this code in action. Moving the mouse over the window changes the coordinate position.


Figure 1. Getting mouse position
Starting Screen

The Component class also has a getMousePosition() method that returns a Point object. The Point returned by getMousePosition() is the mouse position based off the component's coordinate space. Calling the getLocation() method of PointerInfo works in the coordinate space for the whole graphics device (that is, the screen) for a single screened system.

If you aren't familiar with the java.awt.Robot class, the Robot class allows you to move the mouse position. The class has been around since the 1.3 timeframe and includes an appropriately named mouseMove() method that has arguments for x and y coordinates. So now, not only can you move the mouse, but you can discover its position, too.


z-order and AlwaysOnTop

The concept of z-order describes a third dimension in which to place components and their windows. x and y positioning define the horizontal and vertical positions, respectively, with (0, 0) at the top-left corner of the screen. Adding z-order into the mix allows you to control how components are drawn on top of each other.

At the container level, you get two new methods, setComponentZOrder(Component c, int layer) and getComponentZOrder(Component c). The layer passed into the setComponentZOrder() method starts with 0 as the highest layer, drawn last, on top of everything else, with increasing numbers under that.

To demonstrate, the program in Listing 3 creates three components and places them one on top of another. Working with z-order involves several steps. First, you need to disable the layout manager for the container: setLayout(null). If you don't, and add components with the z-order set, it won't matter as there will be no overlapping of components. Of course, if you are using a custom layout manager that overlaps components, that works, too.

Next, you add the components to the container, without any layout constraints. You then set the z-order by calling setComponentZOrder() for each component in the container. As an additional step, for the overlapping components to draw correctly, the container containing the overlapping components must have their optimized drawing disabled, by having their isOptimizedDrawingEnabled() method return false. This last bit is done by creating a JPanel subclass, as there is no setOptimizedDrawingEnabled() method.


Listing 3. z-order and AlwaysOnTop

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

public class Zs {

  public static void main(String args[]) {
    Runnable runnable = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("Z-Ordering");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton top = new JButton("Top");
        JButton middle = new JButton("Middle");
        JButton bottom = new JButton("Bottom");

        int x=25;
        int y=75;
        int width=100;
        int height=50;
        int overlap = 25;
        int widthDelta = width - overlap;
        int heightDelta = height - overlap;

        top.setBounds(x, y, width, height);
        middle.setBounds(x + widthDelta, y - heightDelta,
          width, height);
        bottom.setBounds(x + (widthDelta) * 2, y - (heightDelta) * 2,
          width, height);

        JPanel contentPane = new JPanel() {
          public boolean isOptimizedDrawingEnabled() {
            return false;
          }
        };
        contentPane.setLayout(null);
        contentPane.add(top);
        contentPane.add(middle);
        contentPane.add(bottom);
        contentPane.setComponentZOrder(top, 0);
        contentPane.setComponentZOrder(middle, 1);
        contentPane.setComponentZOrder(bottom, 2);
        frame.setContentPane(contentPane);
        frame.setSize(300, 200);
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runnable);
  }
}

Figure 2 shows the results of the code in Listing 3.


Figure 2. z-order
Z-Ordering

Not only can you control the z-order for individual components within a container, but you can also manage z-order of windows, or at least say which one should go on top. Sure, you can call the toFront() method to make a particular window move to the front, but now with the Java 5.0 platform, you have the new setAlwaysOnTop() method of the Window class. When a window has its alwaysOnTop property set to true, it will always appear on top of other windows. The other windows can still have their components selected, but those windows with alwaysOnTop set to false (the default setting) will remain in the background.

Listing 4 demonstrates this behavior:


Listing 4. z-order and AlwaysOnTop

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

public class Top {

  public static void main(String args[]) {
    Runnable runnable = new Runnable() {
      public void run() {
        JFrame frame = new JFrame("Topper");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JDialog one = new JDialog(frame, "One");
        one.add(new JButton("One"), BorderLayout.CENTER);
        one.setSize(100, 100);
        one.setLocation(25, 25);
        one.setVisible(true);

        JDialog two = new JDialog(frame, "Two");
        two.add(new JButton("Two"), BorderLayout.CENTER);
        two.setSize(100, 100);
        two.setLocation(50, 50);
        two.setVisible(true);

        JDialog three = new JDialog(frame, "Three");
        three.add(new JButton("Three"), BorderLayout.CENTER);
        three.setSize(100, 100);
        three.setLocation(75, 75);
        three.setVisible(true);

        two.setAlwaysOnTop(true);

        frame.setSize(300, 200);
        frame.setVisible(true);
      }
    };
    EventQueue.invokeLater(runnable);
  }
}

Figure 3 shows the results of Listing 4.


Figure 3. Layering windows
Z-Ordering

Untrusted applications need an AWTPermission in their policy file with a target name of setWindowAlwaysOnTop, which prevents malicious users from overriding the whole desktop, making it appear real while the underlying application fishes for information.

Only one active window should have the alwaysOnTop property to true. If multiple windows are set to true, behavior is undefined and likely to be platform-specific.


Resources

About the author

Author photo

John Zukowski conducts strategic Java consulting with JZ Ventures, Inc. and is working with SavaJe Technologies to develop a next-generation mobile phone platform. His latest books are The Definitive Guide to Java Swing, Third Edition (Apress, June 2005) and Mastering Java 2, J2SE 1.4 (Sybex, April 2002)

Comments



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=83808
ArticleTitle=Taming Tiger: AWT grows up
publish-date=05242005
author1-email=jaz@zukowski.net
author1-email-cc=jaloi@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers