I have a Swing app with a main frame and some other forms loaded inside it. I Need to implement a general method to set the hand cursor for all buttons on any form.
This is similar of what we do with css on web pages (input[type=button] { cursor:pointer; }
)
Walking the tree like @Madprogrammer suggested is the method if you want to change the cursor dynamically and/or on a particular form.
Just for fun (and to show-off SwingX again :) - if you want to install that cursor globally and then don't care about, install a ui-delegate which takes care of it. In SwingX, it's as simple as implementing and plugging a custom button addon. The side-effect is the same as in the other answer (though can't be solved as in that). The usual drawback (as always when installing custom ui delegates) is the need to subclass and plug-in delegates for all LAFs.
public class ButtonCursorAddon extends AbstractComponentAddon {
/**
* @param name
*/
protected ButtonCursorAddon() {
super("RolloverCursor");
}
@Override
protected void addBasicDefaults(LookAndFeelAddons addon,
DefaultsList defaults) {
UIManager.getDefaults().remove("ButtonUI");
defaults.add("ButtonUI", "org.jdesktop.swingx.plaf.ButtonCursorAddon$BasicButtonCursorUI");
}
@Override
protected void addMetalDefaults(LookAndFeelAddons addon,
DefaultsList defaults) {
UIManager.getDefaults().remove("ButtonUI");
defaults.add("ButtonUI", "org.jdesktop.swingx.plaf.ButtonCursorAddon$MetalButtonCursorUI");
}
@Override
protected void addWindowsDefaults(LookAndFeelAddons addon,
DefaultsList defaults) {
UIManager.getDefaults().remove("ButtonUI");
defaults.add("ButtonUI", "org.jdesktop.swingx.plaf.ButtonCursorAddon$WindowsButtonCursorUI");
}
@Override
protected void addNimbusDefaults(LookAndFeelAddons addon,
DefaultsList defaults) {
UIManager.getDefaults().remove("ButtonUI");
defaults.add("ButtonUI", "org.jdesktop.swingx.plaf.ButtonCursorAddon$SynthButtonCursorUI");
}
public static class BasicButtonCursorUI extends BasicButtonUI {
public static ComponentUI createUI(JComponent c) {
return new BasicButtonCursorUI();
}
@Override
protected BasicButtonListener createButtonListener(AbstractButton b) {
return new BasicHyperlinkListener(b);
}
}
public static class SynthButtonCursorUI extends SynthButtonUI {
public static ComponentUI createUI(JComponent c) {
return new SynthButtonCursorUI();
}
@Override
protected BasicButtonListener createButtonListener(AbstractButton b) {
return new BasicHyperlinkListener(b);
}
}
public static class MetalButtonCursorUI extends MetalButtonUI {
public static ComponentUI createUI(JComponent c) {
return new MetalButtonCursorUI();
}
@Override
protected BasicButtonListener createButtonListener(AbstractButton b) {
return new BasicHyperlinkListener(b);
}
}
public static class WindowsButtonCursorUI extends WindowsButtonUI {
public static ComponentUI createUI(JComponent c) {
return new WindowsButtonCursorUI();
}
@Override
protected BasicButtonListener createButtonListener(AbstractButton b) {
return new BasicHyperlinkListener(b);
}
}
}
// usage: plug-in once in your application code (before creating any buttons)
static {
LookAndFeelAddons.contribute(new ButtonCursorAddon());
}
I get this error: UIDefaults.getUI() failed: no ComponentUI class
Works for me - when registering the ui class with the UIManager, it needs the fully qualified class name to instantiate the delegate from:
// here the ButtonCursorUI is in package
// org.jdesktop.swingx.plaf
defaults.add("ButtonUI", "org.jdesktop.swingx.plaf.ButtonCursorAddon$WindowsButtonCursorUI");
// in another package that would be
defaults.add("ButtonUI", myPackageName + ".ButtonCursorAddon$WindowsButtonCursorUI");
Typically, you would have the different delegates in LAF specific subpackages of something.plaf (instead of in the addon itself) But then, it's an example :-)
Basically, you'll have to walk the container and sub containers...
Be careful though, you'll be surprised by what is a button
public static void setButtonCursor(JComponent component, Cursor cursor) {
for (Component comp : component.getComponents()) {
if (comp instanceof JButton) {
comp.setCursor(cursor);
} else if (comp instanceof JComponent) {
setButtonCursor((JComponent)comp, cursor);
}
}
}
This has the nice side effect of walking into JComboBox
s (among other components) and changing the cursor for their drop buttons, so be careful ;)