2

I'm creating a custom button, and I'm having trouble getting it to look right on most of the built-in PLAFs.

Here's my code

public MyButton(String text, Icon icon) {
    if (icon == null) icon = createDefaultIcon();

    mainButton = new JButton(text);
    popupButton = new JButton(icon);

    removeBorder(mainButton);
    removeBorder(popupButton);

    setModel(new DefaultButtonModel());
    setBorder(UIManager.getBorder("Button.border"));

    int popupButtonWidth = popupButton.getPreferredSize().width;
    int popupButtonHeight = mainButton.getPreferredSize().height;
    Dimension popupButtonSize = new Dimension(popupButtonWidth, popupButtonHeight);

    popupButton.setMinimumSize(popupButtonSize);
    popupButton.setPreferredSize(popupButtonSize);
    popupButton.setMaximumSize(popupButtonSize);

    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
    add(mainButton);
    add(new JSeparator(VERTICAL));
    add(popupButton);
}

private void removeBorder(JButton button) {
    Border border = button.getBorder();

    if (border instanceof CompoundBorder) {
         button.setBorder(((CompoundBorder) border).getInsideBorder());
    } else {
        button.setBorder(BorderFactory.createEmptyBorder());
    }
}

Here is how the button looks in the PLAFs installed on my computer

Metal

My Custom Button Metal PLAF Example

Nimbus

My Custom Button Nimbus PLAF Example

CDE/Motif

My Custom Button CDE/Motif PLAF Example

Mac OS X

My Custom Button Mac OS PLAF Example

CDE/Motif is the only one that works properly. I looked at the source for some of the ButtonUIs, and it seems they can ignore the background color and the borders. Unfortunately the background color and the borders are what I need to set. How do I get my custom button to support the built-in PLAFs correctly?

Edit: As requested, here's the code I used to produce the images

public class MyButtonDemo implements Runnable {

    public void run() {
        // Change the array index to get a different PLAF
        try {
            UIManager.setLookAndFeel(UIManager.getInstalledLookAndFeels()[0].getClassName());
        } catch (Exception ignored) { }

        JFrame frame = new JFrame();
        frame.getContentPane().setLayout(new FlowLayout());
        frame.getContentPane().add(new MyButton("My Button", null);
        frame.getContentPane().add(new JButton("Normal Button"));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MyButtonDemo());
    }

}
Community
  • 1
  • 1
Eva
  • 4,397
  • 5
  • 43
  • 65
  • The example [incorrectly uses `setXxxSize()`](http://stackoverflow.com/q/7229226/230513). – trashgod Jul 28 '12 at 22:49
  • How would I get the buttons to have the same height without setting the size? – Eva Jul 28 '12 at 22:50
  • The result would depend, in part, on the layout. Please edit your question to include an [sscce](http://sscce.org/) that exhibits the problem you describe. – trashgod Jul 28 '12 at 22:55
  • *"I'm creating a custom button"* Why? What does it do that a normal button does not? If 'nothing', why make it look different? – Andrew Thompson Jul 29 '12 at 00:22
  • 1
    @AndrewThompson by the naming (popup for the second), it sounds like an attempt on a split button – kleopatra Jul 29 '12 at 08:19
  • @AndrewThompson It is a split button. – Eva Jul 29 '12 at 11:05
  • @trashgod I want the inner buttons to be the same size regardless of the layout of the Container that holds MyButton. Is there a way to make a layout independent size requirement without explicitly setting the size? – Eva Jul 29 '12 at 11:06

2 Answers2

0

Welcome to the wonderful world of pluggable look & feel. The only real choices you have, that I can think of, is provide. UI delegate for each platform or have a look at at the Syththetic UI

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • How do I access the UI delegate for PLAFs that aren't installed in my computer? – Eva Jul 28 '12 at 10:56
  • It seems I can't even access most of the PLAFs that are installed in my computer. I tried to subclass each of them and the only one that worked was Metal. – Eva Jul 28 '12 at 11:00
0

Not sure what I did, but it's working now for all but Nimbus. Here's the code

public MyButton(String text, Icon icon) {
    arrowIcon = createDefaultArrowIcon();
    mainButton = new JButton(text, icon);
    popupButton = new JButton(arrowIcon);

    mainButton.setBorder(BorderFactory.createEmptyBorder());
    popupButton.setBorder(BorderFactory.createEmptyBorder());

    setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
    add(mainButton);
    add(new JSeparator(VERTICAL));
    add(popupButton);

    setModel(new DefaultButtonModel());
    init(null, null);
}

@Override
public void updateUI() {
    setUI((ButtonUI)UIManager.getUI(this));
}

@Override
public String getUIClassID() {
    return "ButtonUI";
}
Eva
  • 4,397
  • 5
  • 43
  • 65