Hot questions for Using JTextField in look and feel

Top Java Programmings / JTextField / look and feel

Question:

I want to set the inactive background color of a JTextField on a per-component basis. (The inactive colors are shown when calling setEditable(false)).

Calling UIManager.put("TextField.inactiveBackground", new ColorUIResource(Color.YELLOW)); sets the inactive color application-wide.

It can be done under Nimbus LAF like documented here: http://docs.oracle.com/javase/7/docs/api/javax/swing/plaf/nimbus/package-summary.html. Can a similar thing be done when using Windows LAF?


Answer:

I found a solution. Not really a beautiful solution, but a solution nonetheless:

Extend the JTextField class and override the paintComponent method to draw a rectangle in the desired color.

class CustomTextField extends JTextField {
  private Color inactiveColor = UIManager.getColor("TextField.inactiveBackground");

  public void setDisabledBackgroundColor(Color inactiveColor) {
    this.inactiveColor = inactiveColor;
    repaint();
  }

  @Override
  protected void paintComponent(Graphics g) {
    if (!isEditable() || !isEnabled()) {
      setOpaque(false);
      g.setColor(inactiveColor);
      g.fillRect(0, 0, getWidth(), getHeight());
    } else {
      setOpaque(true);
    }
    super.paintComponent(g);
  }
}

Question:

I was surprise to see that JTextField stopped responding to delete action if you apply a new (Basic)LookAndFeel for the application.

Bellow is the complete code for this:

import javax.swing.*;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.basic.BasicLookAndFeel;
import java.awt.*;
import java.util.logging.Logger;

public class App2 {
     private static final Logger log =  Logger.getLogger(App2.class.getCanonicalName());

     public static void main(String args[]){
         setUI();

         JFrame f = new JFrame();

         JTextField tf = new JTextField();
         f.add(tf);



         f.setSize(300, 300);
         f.setVisible(true);
           f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
     }

  static void setUI(){
       try {
            javax.swing.UIManager.setLookAndFeel(new DummyLookAndFeel());
       } catch ( UnsupportedLookAndFeelException ex) {
             log.warning("Setting UI not ok : " + ex.getMessage());
       }
   }
}

class DummyLookAndFeel extends BasicLookAndFeel {
     @Override
     protected void initComponentDefaults(UIDefaults table) {
         table.put("TextField.background", new ColorUIResource(Color.RED));
     }

     @Override
     public String getName() {
         return "Just a fancy name";
     }

     @Override
     public String getID() {
         return "Something unique";
     }

     @Override
     public String getDescription() {
         return "A very very long description";
     }

     @Override
     public boolean isNativeLookAndFeel() {
         return false;
     }

     @Override
     public boolean isSupportedLookAndFeel() {
         return true;
     }
 }

Any idea of why is happening?


Answer:

It seems that if I change the initComponentDefaults(...) to

protected void initComponentDefaults(UIDefaults table) {
  super.initComponentDefaults(table);

  Object fim = table.get("TextField.focusInputMap");

  Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[] {
                     "ctrl C", DefaultEditorKit.copyAction,
                     "ctrl V", DefaultEditorKit.pasteAction,
                     "ctrl X", DefaultEditorKit.cutAction,
                       "COPY", DefaultEditorKit.copyAction,
                      "PASTE", DefaultEditorKit.pasteAction,
                        "CUT", DefaultEditorKit.cutAction,
             "control INSERT", DefaultEditorKit.copyAction,
               "shift INSERT", DefaultEditorKit.pasteAction,
               "shift DELETE", DefaultEditorKit.cutAction,
                 "shift LEFT", DefaultEditorKit.selectionBackwardAction,
              "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
                "shift RIGHT", DefaultEditorKit.selectionForwardAction,
             "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
                  "ctrl LEFT", DefaultEditorKit.previousWordAction,
               "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
                 "ctrl RIGHT", DefaultEditorKit.nextWordAction,
              "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
            "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
         "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
           "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
        "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
                     "ctrl A", DefaultEditorKit.selectAllAction,
                       "HOME", DefaultEditorKit.beginLineAction,
                        "END", DefaultEditorKit.endLineAction,
                 "shift HOME", DefaultEditorKit.selectionBeginLineAction,
                  "shift END", DefaultEditorKit.selectionEndLineAction,
                 "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
           "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
                     "ctrl H", DefaultEditorKit.deletePrevCharAction,
                     "DELETE", DefaultEditorKit.deleteNextCharAction,
                "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
            "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
                      "RIGHT", DefaultEditorKit.forwardAction,
                       "LEFT", DefaultEditorKit.backwardAction,
                   "KP_RIGHT", DefaultEditorKit.forwardAction,
                    "KP_LEFT", DefaultEditorKit.backwardAction,
                      "ENTER", JTextField.notifyAction,
            "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
             "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
  });

  table.put("TextField.focusInputMap", fieldInputMap);


  table.put("TextField.background", new ColorUIResource(Color.RED));
}

the JTextField seems to be working. It seems that UIDefaults has no entry for "TextField.focusInputMap" (In the example the fim Object is null)

Question:


Answer:

They say a picture paints a thousand words, so here's a 6K word answer.

Note that in Nimbus & Motif PLAFs, the background of the non-editable text field appears same as the editable text field, while in three others, it looks different.

The disabled text field appears different to either the editable or non-editable fields in all PLAFs.

Code

Use this code to test on your system / JRE.

import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.*;
import javax.imageio.ImageIO;
import java.io.*;

public class TextFieldPLAF {

    TextFieldPLAF() {
        initUI();
    }

    public final void initUI() {
        UIManager.LookAndFeelInfo[] lafInfos = UIManager.getInstalledLookAndFeels();
        try {
            for (UIManager.LookAndFeelInfo lAFI : lafInfos) {
                saveImageOfLookAndFeel(lAFI);
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void saveImageOfLookAndFeel(UIManager.LookAndFeelInfo lafi) throws IOException {
        String classname = lafi.getClassName();
        try {
            UIManager.setLookAndFeel(classname);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        JComponent ui = new JPanel(new GridLayout(1, 0));
        ui.setBorder(new TitledBorder(classname));
        int cols = 13;
        JTextField tf;
        tf = new JTextField("Editable & Enabled", cols);
        ui.add(tf);
        tf = new JTextField("Not Editable", cols);
        tf.setEditable(false);
        ui.add(tf);
        tf = new JTextField("Not Enabled", cols);
        tf.setEnabled(false);
        ui.add(tf);
        JOptionPane.showMessageDialog(null, ui);
        BufferedImage bi = new BufferedImage(
                ui.getWidth(), ui.getHeight(), BufferedImage.TYPE_INT_RGB);
        ui.paint(bi.getGraphics());
        File dir = new File(System.getProperty("user.home"));
        File f = new File(dir, String.format("PLAF-%1s.png", classname));
        ImageIO.write(bi, "png", f);
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            new TextFieldPLAF();
        };
        SwingUtilities.invokeLater(r);
    }
}