<< Previous o Trail o Next >> How to Use the Focus Subsystem Many components ??? even those primarily operated with the mouse, such as buttons ??? can be operated with the keyboard. For a key press to affect a component, the component must have the keyboard focus. From the user's point of view, the component with the keyboard focus is generally prominent ??? with a dotted or black border, for example. The window containing the component is also more prominent than other windows onscreen. These visual cues let the user know to which component any typing will relate. Only one component at a time in the -- in JDK 1.4. Prior to the 1.4 release, JComponent methods, such as setNextFocusableComponent, getNextFocusableComponent, requestDefaultFocus, and isManagingFocus, were used to manage the keyboard focus. These methods are now deprecated. Another method, requestFocus, is discouraged because it tries to give the focus to the component's window, which is not always possible. As of JDK 1.4, you should instead use the requestFocusInWindow method, which does not attempt to make the component's window focused. The method returns a boolean value indicating whether the method succeeded. __________________________________________________________________ The rest of this section covers the following topics: * Introduction to the Focus Subsystem -- use the requestFocusInWindow method to set the focus on a component when the window becomes visible. * The ordering is wrong. To fix this issue, you can change the containment hierarchy, you can change the order that the components are added to their containers, or you can create a custom focus traversal policy. For more details see Customizing Focus Traversal. * A component must to be prevented from losing focus, or you need to check a value in a component before it loses focus. Input verification is a solution to this problem. * A custom component is not getting the focus. To fix this issue, you need to make sure that it satisfies all the requirements outlined in Making a Custom Component Focusable. The FocusConceptsDemo example illustrates a few concepts. The FocusConceptsDemo example __________________________________________________________________ -- The KeyboardFocusManager is a critical element of the focus subsystem. It manages state and initiates changes. The keyboard manager tracks the focus owner ??? the component that receives typing from the keyboard. The focused window is the window that contains the focus owner. __________________________________________________________________ JWindow and focus: To use a JWindow component in your GUI, you should know that the JWindow component's owning frame must be visible in order for any components in the window to get the focus. By default, if you do not specify an owning frame for a JWindow component, an invisible owning frame is created for it. The result is that components in the JWindow component might not be able to get the focus. The solution is either to specify a visible owning frame when creating the JWindow component, or to use an undecorated JFrame component instead. -- //Calculate the result and update the GUI. payment = computePayment(amount, rate, numPeriods); paymentField.setText(paymentFormat.format(payment)); } //This method checks input, but should cause no side effects. public boolean verify(JComponent input) { return checkField(input, false); } protected void makeItPretty(JComponent input) { checkField(input, true); -- return checkAmountField(changeIt); } else if (input == rateField) { return checkRateField(changeIt); } else if (input == numPeriodsField) { return checkNumPeriodsField(changeIt); } else { return true; //should not happen } } //Checks that the amount field is valid. If it is valid, //it returns true; otherwise, returns false. If the //change argument is true, this method sets the -- source.selectAll(); } } Note that the verify method is implemented to detect invalid values but does nothing else. The verify method exists only to determine whether the input is valid ??? it should never bring up a dialog-box or cause any other side effects. The shouldYieldFocus method calls verify and, if a values is invalid, sets it to the minimum or maximum value. The shouldYieldFocus method is allowed to cause side effects, in this case, it always formats the text field and may also change its value. In our example, the shouldYieldFocus method always returns true so that the transfer of the focus is never actually prevented. This is just one way -- private MyVerifier verifier = new MyVerifier(); ... amountField.setInputVerifier(verifier); Making a Custom Component Focusable For a component to gain the focus, it must satisfy three requirements: it must be visible, enabled, and focusable. An input map may also be given. For more information about input map, read How to Use Key Bindings. The TrackFocusDemo example defines the simple component Picture. Its constructor is shown below: public Picture(Image image) { -- addMouseListener(this); addFocusListener(this); } The call to the setFocusable(true) method makes the component focusable. If you explicitly give your component key bindings in its WHEN_FOCUSED input map, you do not need to call the setFocusable method. To visually show changes in the focus (by drawing a red border only when the component has the focus), Picture has a focus listener. To gain the focus when the user clicks on the picture, the component -- You can remove the custom focus traversal policy by setting the FocusTraversalPolicy to null, which will restore the default policy. Tracking Focus Changes to Multiple Components In some situations an application may need to track which component has the focus. This information might be used to dynamically update menus or perhaps a status bar. If you need to track the focus only on specific components, it may make sense to implement a focus event listener. If a focus listener is not appropriate, you can instead register a PropertyChangeListener on the KeyboardFocusManager. The property change listener is notified of every change involving the focus, including -- initiates the focus transfer, but it does not immediately move the focus to the Cancel button. When the Start button is disabled, the focus is transferred to the next component (so there is always a component with the focus) and, in this case, it would then move the focus to the text field, not to the Cancel button. There are several situations in which you need to make focus requests after all other changes that might affect the focus applies to: * Hiding the focus owner. * Making the focus owner non-focusable. * Calling the removeNotify method on the focus owner. * Doing any of the above operations to the container of the focus owner, or causing changes to the focus policy so that the container -- All of this API was introduced in JDK 1.4. Method (in Component) Purpose isFocusOwner() Returns true if the component is the focus owner. This method, introduced in JDK 1.4, renders obsolete hasFocus. setRequestFocusEnabled(boolean) isRequestFocusEnabled() (in JComponent) Sets or checks on whether this component should get the focus. Setting the setRequestFocusEnabled to false typically prevents mouse clicks from giving the component the focus, while still allowing keyboard navigation to give the component the focus. This method applies only to components that receive mouse events. For example, you can use this method on a JButton, but not on a JPanel. If you write a custom component it is up to you to honor this property. This method is recommended over the setFocusable method and will allow your program to work better for users employing assistive technologies. setFocusable(boolean) isFocusable() Sets or gets the focusable state of the component. A component must be focusable in order to gain the focus. When a component has been removed from the focus cycle with setFocusable(false), it can no longer be navigated with the keyboard. The setRequestFocusEnabled method is recommended so that your program can be run by users employing assistive technologies. requestFocusInWindow() Requests that this component should get the focus. The component's window must be the current focused window. For this request to be granted a subclass of JComponent must be visible, enabled, and focusable, and have an input map for this request to be granted. It should not be assumed that the component has the focus until it fires a FOCUS_GAINED event. This method is preferred to the requestFocus method, which is platform-dependent. setFocusTraversalKeys(int, Set) getFocusTraversalKeys(int) areFocusTraversalKeysSet(int) (in java.awt.Container) Sets or gets the focus traversal keys for a -- have been set, they are inherited from an ancestor or from the keyboard focus manager. Focus traversal keys can be set for the following directions: KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. If you set the UP_CYCLE_TRAVERSAL_KEYS or the DOWN_CYCLE_TRAVERSAL_KEYS, you must also invoke setImplicitDownCycleTraversal(false) on the focus traversal policy. Creating and Using a Custom FocusTraversalPolicy Class or Method Purpose LayoutFocusTraversalPolicy The class that, by default, determines the focus traversal policy for Swing components. getComponentAfter(Container, Component) Given the component that is passed as input, returns the component that should next have the focus. getComponentBefore(Container, Component) Given the component that is passed as input, returns the component that should have the focus before this component. The method is used for backward tabbing. getDefaultComponent(Container) (in javax.swing.SortingFocusTraversalPolicy) Returns the component that should have the default focus. getFirstComponent(Container) Returns the first component in the traversal cycle. getInitialComponent(Container) Returns the component that should receive the focus when a window is made visible for the first time. getLastComponent(Container) Returns the last component in the traversal cycle. setFocusTraversalPolicy(FocusTraversalPolicy) getFocusTraversalPolicy(FocusTraversalPolicy) (in java.awt.Container) Sets or gets the focus traversal policy or -- (in InputVerifier) When a component has an input verifier, this method is called by the system to determine whether the focus can leave this component. This method may cause side effects, such as bringing up a dialog-box. If this method returns false, the focus remains on the component passed in to the method. verify(JComponent) (in InputVerifier) You need to override this method to check that the component's input is valid. It should return true if valid, otherwise return false. This method should not cause any side effects, such as bringing up a dialog-box. This method is called by shouldYieldFocus. setInputVerifier(inputVerifier) getInputVerifier() (in JComponent) Sets or gets the input verifier assigned to the component. By default, components have no input verifier. setVerifyInputWhenFocusTarget(boolean) getVerifyInputWhenFocusTarget() (in JComponent) Sets or gets whether the input verifier for the current focus owner is called before this component requests the focus. The default is true. This method should be set to false for components, such as a Cancel button or a scroll bar, that should receive the focus even if input is invalid. KeyboardFocusManager Properties This table defines the bound properties for KeyboardFocusManager. A listener can be registered for these properties by calling -- Property Purpose focusOwner The component that currently receives key events. permanentFocusOwner The component that most recently received a permanent FOCUS_GAINED event. Typically the same as focusOwner, unless a temporary focus change is currently in effect. focusedWindow The window that is or that contains the focus owner. activeWindow The component must always be either a Frame or a Dialog. The active window is either the focused window, or the first frame or dialog-box that is an owner of the focused window. defaultFocusTraversalPolicy The default focus traversal policy, which can be set by the setFocusTraversalPolicy method of the Container class. forwardDefaultFocusTraversalKeys The set of default focus keys for a -- backward traversal. For multi-line text components these keys default to Control-Shift-Tab. For all other components these keys default to Shift-Tab and Control-Shift-Tab. upCycleDefaultFocusTraversalKeys The set of default focus keys for an up cycle. These keys are null, by default, for Swing components. If you set these keys on the KeyboardFocusManager, or if you set the downCycleFocusTraversalKeys on a focus cycle root, you must also invoke the setImplicitDownCycleTraversal(false) method on the focus traversal policy. downCycleDefaultFocusTraversalKeys The set of default focus keys for a down cycle. These keys are null, by default, for Swing components. If you set these keys on the KeyboardFocusManager, or if you set the upCycleFocusTraversalKeys on a focus cycle root, you must also invoke the setImplicitDownCycleTraversal(false) method on the focus traversal policy. currentFocusCycleRoot The container that is the current focus cycle root. Examples that Use Focus