Search code examples
javaswingresizejbuttonlook-and-feel

How to set a default preferred size (redefining UI) in a *ComponentUI class (Swing app)?


I extended the system look and feel to draw custom JButton.

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
UIManager.put("ButtonUI", "com.my.package.MyButtonUI");

With com.my.package.MyButtonUI:

public class MyButtonUI extends BasicButtonUI {

    public static final int BTN_HEIGHT = 24;
    private static final MyButtonUI INSTANCE = new MyButtonUI ();

    public static ComponentUI createUI(JComponent b) {
        return INSTANCE;
    }

    @Override
    public void paint(Graphics g, JComponent c) {
        AbstractButton b = (AbstractButton) c;
        Graphics2D g2d = (Graphics2D) g;
        GradientPaint gp;
        if (b.isEnabled()) {
            gp = new GradientPaint(0, 0, Color.red, 0, BTN_HEIGHT * 0.6f, Color.gray, true);
        } else {
            gp = new GradientPaint(0, 0, Color.black, 0, BTN_HEIGHT * 0.6f, Color.blue, true);
        }
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, b.getWidth(), BTN_HEIGHT);
        super.paint(g, b);
    }

    @Override
    public void update(Graphics g, JComponent c) {
        AbstractButton b = (AbstractButton) c;
        b.setForeground(Color.white);
        paint(g, b);
    }
}

Now I would like to add that constraint on these buttons: I want the buttons to have size of 70x24 except if a setPreferredSize() has been called in the client code. How can I do that?

Note: If I put a setPreferredSize() in the MyButtonUI.update() method, it overrides the client setPreferredSize(), then all my buttons get the same size.

Thank you.

EDIT:

Thanks to Guillaume, I overrided getPreferredSize() (in MyButtonUI) like this:

@Override
public Dimension getPreferredSize(JComponent c) {
    AbstractButton button = (AbstractButton) c;
    int width = Math.max(button.getWidth(), BUTTON_WIDTH);
    int height = Math.max(button.getHeight(), BUTTON_HEIGHT);
    return new Dimension(width, height);
}

and it works fine.


Solution

  • Simply override the method getPreferredSize() in your class MyButtonUI. If a programmer voluntarily sets the preferred size to something else, your code will not be called. That is the default behaviour of JComponent.

    See the code of getPreferredSize():

    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        Dimension size = null;
        if (ui != null) {
            size = ui.getPreferredSize(this);
        }
        return (size != null) ? size : super.getPreferredSize();
    }