Õ¾ÄÚËÑË÷: ÇëÊäÈëËÑË÷¹Ø¼ü´Ê
µ±Ç°Ò³Ãæ: ͼÊéÊ×Ò³ > SWT: The Standard Widget Toolkit

3.1 Mouse Events - SWT: The Standard Widget Toolkit

Previous Section  < Day Day Up >  Next Section

3.1 Mouse Events

When a mouse button is pressed or the mouse is moved, a mouse event is created and normally delivered to the control that is beneath the cursor. However, when a mouse button is pressed and held, and the mouse is moved outside of the control (perhaps into another control or over the desktop), events are delivered to the original control that got the mouse press. When the mouse button is released, events are delivered normally. This temporary redirection of events is called mouse capture or grabbing. The control that receives the events is called the grab control. Mouse capture happens automatically in SWT. It is something that you need to be aware of but need not be concerned with. Most programmers simply expect the mouse to behave in this manner.[3]

[3] On X Windows, grabbing is built into the operating system.

3.1.1 Mouse Buttons, Coordinates, and the State Mask

When the mouse is pressed or released, the button field of the mouse event that is generated contains the number of the button that was pressed. Mouse buttons are numbered from left to right, using consecutive integer values starting from 1. For users who are left-handed (and configure the operating system for a left-handed person), the button numbering scheme remains the same but the buttons are arranged physically from right to left. This mapping for left-handed users is transparent to SWT and to your application.

When a mouse event occurs, the x and y coordinates are reported in the corresponding fields of the event. These coordinates are relative to the control that received the event at the time the event occurred.[4] Because the user may have moved the mouse between the time the event occurred and the time it was delivered, the physical location of the mouse can be different from the coordinates reported in the event.[5] Recording the position of the mouse in the event prevents the system from being sensitive to these movements. You should always use the coordinates in the mouse event.

[4] Coordinate systems for controls and drawing are described in Control Fundamentals and Graphics Fundamentals.

[5] If you need the exact location of the mouse at any given moment, you can use Display.getCursorLocation() (see the Display chapter for more on this).

Mouse events use the stateMask field of the event to indicate the mouse state. In the same manner as key modifiers, the stateMask field contains the state of the mouse immediately prior to the event. For example, if no mouse buttons or keyboard modifier keys have already been pressed, when the left mouse button is pressed, a mouse down event is issued with the button field set to 1 and the stateMask set to zero. The stateMask field does not contain the "button 1" state mask. However, provided that the user holds the left button down, the stateMask field of subsequent mouse events will contain this mask.

Mouse state is represented by constants in the class SWT. Table 3.1 shows the mouse state mask values.

Table 3.1. Mouse State Masks

State Mask

Description

SWT.BUTTON1

Button 1 was down

SWT.BUTTON2

Button 2 was down

SWT.BUTTON3

Button 3 was down

SWT.BUTTON_MASK

Bitwise-OR of all valid button masks


The constant SWT.BUTTON_MASK contains every mouse mask and is used in a manner similar to SWT.MODIFIER_MASK:






//WRONG – broken when new mouse masks are added

int bits = SWT.BUTTON1 | SWT.BUTTON2 | SWT.BUTTON3;

if ((event.stateMask & bits) == 0) {

    System.out.println ("No mouse buttons are down");

}



//CORRECT – works when new mouse masks are added

if ((event.stateMask & SWT.BUTTON_MASK) == 0) {

    System.out.println ("No mouse buttons are down");

}


Why Is the Button Field an Integer Instead of a Button Constant?

Although it's pretty clear that the integer 1 can represent the first button on the mouse and so on, it would have been more consistent with the rest of SWT to reuse the button state masks. For example, the keyboard constant SWT.SHIFT is used to represent both the <Shift> key and the modifier mask. Unfortunately, this inconsistency was found too late in the release cycle, before 1.0. It was discovered that programmers were writing code such as "event.button == SWT.BUTTON1," which looks nice but is incorrect. Sadly, nothing can be done about this problem without breaking too many existing programs.


3.1.2 Mouse Events

Table 3.2 shows the mouse-related events that are provided by SWT.

Table 3.2. Mouse Events

Untyped Event

Meaning

SWT.MouseDown

The mouse was pressed in a control

SWT.MouseUp

The mouse was released in a control

SWT.MouseMove

The mouse was moved in a control

SWT.MouseEnter

The mouse entered a control

SWT.MouseExit

The mouse exited a control

SWT.MouseDoubleClick

The mouse was double-clicked in a control

SWT.MouseHover

The mouse hovered in a control

Typed Event

Listener

Methods

MouseEvent

MouseListener (and MouseAdapter)

mouseDoubleClick(MouseEvent)

mouseDown(MouseEvent)

mouseUp(MouseEvent)

MouseEvent

MouseMoveListener

mouseMove(MouseEvent)

MouseEvent

MouseTrackListener (and MouseTrackAdapter)

mouseEnter(MouseEvent)

mouseExit(MouseEvent)

mouseHover(MouseEvent)


The relevant event fields during mouse events are shown in Table 3.3.

Table 3.3. Public Fields of Class Event That Are Valid during the Mouse Events

Field

Meaning

button

The button that was pressed or released

x

The x coordinate where the mouse event occurred

y

The y coordinate where the mouse event occurred

stateMask

A bit-mask that indicates the mouse and keyboard state


The mouse up, down, and move events are self-evident, mapping directly to the operating system equivalents. It is important to note that only SWT.MouseDown and SWT.MouseUp use the button field. When the mouse is moved, even when a button is held down, this field is zero. This makes sense because the mouse can be moved while more than one button is pressed but the field can represent only a single button. In this case, the stateMask field is used to determine button state.

As expected, SWT.MouseEnter and SWT.MouseExit events occur when the user moves the mouse into and out of a control. SWT.MouseHover occurs when the mouse "lingers" within a control. The time period and exact criteria for SWT.MouseHover are platform-specific.

Double-Click Events

The SWT.MouseDoubleClick event is sent when the mouse is rapidly pressed and released twice. Once again, the exact time period and criteria for double-click are platform-specific. For example, on some platforms, the mouse must not only be pressed and released twice, but it must remain within a specific area that was determined by the first mouse press. The ordering of SWT.MouseDown, SWT.MouseUp, and SWT.MouseDoubleClick events is as follows.

  1. SWT.MouseDown

  2. SWT.MouseUp

  3. SWT.MouseDown

  4. SWT.MouseDoubleClick

  5. SWT.MouseUp

The implications of this event ordering are subtle. When writing your own control, if it issues an SWT.Selection event on a single click and the SWT .DefaultSelection event on double-click, both these events need to be sent from SWT.MouseUp. Implementing selection the obvious way by sending SWT.Selection from SWT.MouseDown and SWT.DefaultSelection from SWT .MouseDoubleClick means that when the user double-clicks on your control, you will send two SWT.Selection events and one SWT.DefaultSelection. Sending SWT.Selection from SWT.MouseUp has the further advantage that your control can implement "drag selection" and "scroll while selecting" behavior.

Displaying Mouse Events

The following example prints every mouse event that occurs in a shell.






public static void main(String[] args) {

    Display display = new Display();

    Shell shell = new Shell(display);

    Listener mouseListener = new Listener() {

        public void handleEvent(Event e) {

            String string = "UNKNOWN";

            switch (e.type) {

                case SWT.MouseDown: string = "DOWN"; break;

                case SWT.MouseUp: string = "UP"; break;

                case SWT.MouseMove: string = "MOVE"; break;

                case SWT.MouseDoubleClick:

                    string = "DOUBLE";

                    break;

                case SWT.MouseEnter: string="ENTER"; break;

                case SWT.MouseExit: string = "EXIT"; break;

                case SWT.MouseHover: string="HOVER"; break;

            }

            string += ": stateMask=0x"

                + Integer.toHexString(e.stateMask);

            if ((e.stateMask & SWT.CTRL) != 0)

                string += " CTRL";

            if ((e.stateMask & SWT.ALT) != 0)

                string += " ALT";

            if ((e.stateMask & SWT.SHIFT) != 0)

                string += " SHIFT";

            if ((e.stateMask & SWT.COMMAND) != 0)

                string += " COMMAND";

            if ((e.stateMask & SWT.BUTTON1) != 0)

                string += " BUTTON1";

            if ((e.stateMask & SWT.BUTTON2) != 0)

                string += " BUTTON2";

            if ((e.stateMask & SWT.BUTTON3) != 0)

                string += " BUTTON3";

            string += ", button=0x"

                + Integer.toHexString(e.button);

            string += ", x=" + e.x + ", y=" + e.y;

            System.out.println(string);

        }

    };

    shell.addListener(SWT.MouseDown, mouseListener);

    shell.addListener(SWT.MouseUp, mouseListener);

    shell.addListener(SWT.MouseMove, mouseListener);

    shell.addListener(SWT.MouseDoubleClick, mouseListener);

    shell.addListener(SWT.MouseEnter, mouseListener);

    shell.addListener(SWT.MouseExit, mouseListener);

    shell.addListener(SWT.MouseHover, mouseListener);

    shell.setSize(200, 200);

    shell.open();

    while (!shell.isDisposed()) {

        if (!display.readAndDispatch()) display.sleep();

    }

    display.dispose();

}


3.1.3 Detecting a Context Menu Request

To detect when the user has requested a context menu, SWT defines the SWT.MenuDetect event (Table 3.4).

Table 3.4. The MenuDetect Event

Untyped Event

Meaning

SWT.MenuDetect

The user requested a context menu


The relevant event fields during an SWT.MenuDetect event are shown in Table 3.5.

Table 3.5. Public Fields of Class Event That Are Valid during SWT.MenuDetect

Field

Meaning

x

The x coordinate where the menu should be displayed

y

The y coordinate where the menu should be displayed

doit

A boolean that is used to cancel the operation


The SWT.MenuDetect event is very flexible. Depending on the platform, some controls have a built-in context menu that the operating system provides.[6] Others have a context menu that was assigned by the application program. Some controls have no context menu at all. In any case, SWT.MenuDetect allows you to detect when a menu is requested and provide your own context menu at that time. You can either display it yourself by using the x and y coordinates in the event or assign the new menu using Control.setMenu(). The following example code does just that.

[6] Windows XP and GTK do this, providing cut, copy, paste operations, as well as the ability to insert Unicode characters.






static int Count;

public static void main(String[] args) {

    Display display = new Display();

    final Shell shell = new Shell(display);

    shell.addListener(SWT.MenuDetect, new Listener() {

        public void handleEvent(Event event) {

          Menu menu = shell.getMenu();

          if (menu != null) menu.dispose();

          menu = new Menu(shell, SWT.POP_UP);

          MenuItem item = new MenuItem(menu, SWT.PUSH);

          item.setText("Menu " + Count++);

          shell.setMenu(menu);

        }

    });

    shell.pack();

    shell.open();

    while (!shell.isDisposed()) {

        if (!display.readAndDispatch()) display.sleep();

    }

    display.dispose();

}


Notice that a new menu with a different numbered menu item is created each time the MenuDetect event is received.

The doit field in the event is used to override the built-in context menu that is found in some controls or a menu that was supplied previously using setMenu(). Setting this field to false stops this menu from being displayed. You can provide your own menu (opening it in the listener code) or choose not to display a menu by setting this field to false.

One final note: SWT.MenuDetect is also sent when the user requests a context menu using the keyboard.

3.1.4 Detecting a Drag-and-Drop Request

To determine when a drag-and-drop operation should be initiated, the SWT.DragDetect event is used (Table 3.6).

Table 3.6. The DragDetect Event

Untyped Event

Meaning

SWT.DragDetect

The user requested a drag-and-drop operation


The relevant event fields during an SWT.DragDetect event are shown in Table 3.7.

Table 3.7. Public Fields of Class Event That Are Valid during SWT.DragDetect

Field

Meaning

x

The x coordinate where the mouse event occurred

y

The y coordinate where the mouse event occurred


Listening for SWT.DragDetect does not start a drag-and-drop operation. Rather, it detects the platform-specific mouse gesture used to indicate that a drag should start. On some platforms, drag operations are initiated using the middle mouse button. On others, the left mouse button is used. On some platforms, to distinguish a drag gesture from a mouse selection, the user moves the mouse a certain number of pixels while keeping it pressed.

Application programmers can listen for SWT.DragDetect and use it to decide when to move their own objects without requiring them to use the SWT drag-and-drop support.[7] The advantage over simply using an SWT .MouseDown to do this is that users are familiar with the standard mouse drag gesture from other applications on the desktop. By using SWT.DragDetect, the application will follow the platform conventions.

[7] The drag-and-drop support provided by SWT allows applications to plug into the native drag-and-drop mechanisms found on most modern platforms. It is an advanced topic that is not covered in this book but is touched on in the FileExplorer chapter. For more information, see the article Drag and Drop—Adding Drag and Drop to an SWT Application at www.eclipse.org and the Javadoc for the classes in the package org.eclipse.swt.dnd.

    Previous Section  < Day Day Up >  Next Section