Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTextField - Reset Border to System Default

I am trying to color the Border of a JTextField red and then change it back to "normal" later on. When I am using Linux (furthermore Ubuntu), the initial Border differs from the Border that you get by using UIManager.getBorder("TextField.border"); one of them is a SynthBorder and one is a FieldBorder. The "correct" one would be the SynthBorder.

SSCCE:

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main
{
  private static boolean switched;

  public static void main( final String[] args )
      throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException
  {
    UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );

    JFrame frame = new JFrame( "Test border change" );
    frame.getContentPane().setLayout( new BoxLayout( frame.getContentPane(), BoxLayout.LINE_AXIS ) );
    JTextField tf = new JTextField();
    JButton button = new JButton( "Switch" );
    button.addActionListener( action ->
    {
      if ( switched )
      {
        tf.setBorder( UIManager.getBorder( "TextField.border" ) );
        switched = !switched;
      }
      else
      {
        tf.setBorder( BorderFactory.createLineBorder( Color.RED ) );
        switched = !switched;
      }
    } );
    frame.getContentPane().add( tf );
    frame.getContentPane().add( button );
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    frame.pack();
    frame.setVisible( true );
  }
}

I have already tried:

  • using JComponent.updateUI() (no effect)
  • nulling the border (ruins the layout)
  • preserving it (not a proper way)

Does anyone have a better idea?

like image 571
Marcel Avatar asked Jan 22 '26 09:01

Marcel


2 Answers

You can get the default border in the UIManager with this code:

jTextField2.setBorder(UIManager.getLookAndFeel().getDefaults().getBorder("TextField.border"));
like image 178
nat Avatar answered Jan 24 '26 21:01

nat


When you replace the Border try using:

Border uiBorder = BorderUIResource( BorderFactory.createLineBorder( Color.RED ) );
tf.setBorder( uiBorder );

When you use any wrapper class with "UIResource" this tell the LAF the component is part of the LAF and not a custom implementation

Then to restore the Border:

SwingUtilities.updateComponentTreeUI( tf );

Hopefully this will fake the UI into resetting the LAF properties, specifically the Border.

Read the section from the Swing tutorial on How to Set the LAF for more information.

Of course this is not as efficient as simply saving the Border and resetting it as all properties of the text field will be updated bye the updatComponentTreeUI(...) (if this works).

Still don't see why you can't save the Border. You could use the putClientProperty(...) method of the JComponent class to save the Border and then restore it using the getClientProperty(...) method.

You could even automate this by using adding a PropertyChangeListener to listen for a change in the border. When an event is generated if the getClientProperty(...) returns null, then you save the old value from the PropertyChangeEvent.

like image 28
camickr Avatar answered Jan 24 '26 21:01

camickr