Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an easy way to change the behavior of a Java/Swing control when it gets focus?

For most GUI's I've used, when a control that contains text gets the focus, the entire contents of the control are selected. This means if you just start typing, you completely replace the former contents.

Example: You have spin control that is initialized with the value zero. You tab to it and type "1" The value in the control is now 1.

With Swing, this doesn't happen. The text in the control is not selected and the carat appears at one end or another of the existing text. Continuing the above example:

With a Swing JSpinner, when you tab to the spin control, the carat is at the left. You type "1" and the value in the control is now 10.

This drives me, (and my users) up a wall, and I'd like to change it. Even more important, I'd like to change it globally so the new behavior applies to JTextField, JPasswordField, JFormattedTextField, JTextArea, JComboBox, JSpinner, and so on. The only way I have found to do this to add a FocusAdapter to each control and override the focusGained() method to Do The Right Thing[tm].

There's gotta be an easier, and less fragile way. Please?

EDIT: One additional piece of information for this particular case. The form I am working with was generated using Idea's form designer. That means I normally don't actually write the code to create the components. It is possible to tell Idea that you want to create them yourself, but that's a hassle I'd like to avoid.

Motto: All good programmers are basically lazy.

like image 789
Dale Wilson Avatar asked Sep 15 '08 20:09

Dale Wilson


People also ask

What does setFocusable do in Java?

setFocusable() is actually a method from the Component class in Swing. It lets the component (in your case, JPanel which extends Component ) have the power of getting focused.

What is replacing Java Swing?

Hint: Oracle has developed JavaFX to replace both Swing and AWT. Since Java SE 7, update 6 it is bundled with Java SE. "JavaFX is a set of graphics and media packages that enables developers to (...) deploy rich client applications that operate consistently across diverse platforms" [1].

Is Java Swing Easy?

It is a part of the JFC( Java Foundation Classes). It is build on top of the AWT API and entirely written in java. It is platform independent unlike AWT and has lightweight components. It becomes easier to build applications since we already have GUI components like button, checkbox etc.

Is Swing in Java outdated?

Swing and AWT will continue to be supported on Java SE 8 through at least March 2025, and on Java SE 11 (18.9 LTS) through at least September 2026.


2 Answers

When I've needed this in the past, I've created subclasses of the components I wanted to add "auto-clearing" functionality too. eg:

public class AutoClearingTextField extends JTextField {
   final FocusListener AUTO_CLEARING_LISTENER = new FocusListener(){
      @Override
      public void focusLost(FocusEvent e) {
         //onFocusLost(e);
      }

      @Override
      public void focusGained(FocusEvent e) {
         selectAll();
      }
   };

   public AutoClearingTextField(String string) {
      super(string);
      addListener();
   }

   private void addListener() {
      addFocusListener(AUTO_CLEARING_LISTENER);      
   }
}

The biggest problem is that I haven't found a "good" way to get all the standard constructors without writing overrides. Adding them, and forcing a call to addListener is the most general approach I've found.

Another option is to watch for ContainerEvents on a top-level container with a ContainerListeer to detect the presence of new widgets, and add a corresponding focus listener based on the widgets that have been added. (eg: if the container event is caused by adding a TextField, then add a focus listener that knows how to select all the text in a TextField, and so on.) If a Container is added, then you need to recursively add the ContainerListener to that new sub-container as well.

Either way, you won't need to muck about with focus listeners in your actual UI code -- it will all be taken care of at a higher level.

like image 190
rcreswick Avatar answered Sep 25 '22 00:09

rcreswick


I haven't tried this myself (only dabbled in it a while ago), but you can probably get the current focused component by using: KeyboardFocusManager (there is a static method getCurrentKeyboardFocusManager()) an adding a PropertyChangeListener to it. From there, you can find out if the component is a JTextComponent and select all text.

like image 23
Avrom Avatar answered Sep 22 '22 00:09

Avrom