Swing应用程序中所有按钮的光标更改

4

我有一个Swing应用程序,其中包含一个主窗体和一些其他加载在其内的表单。我需要实现一个通用方法来设置任何表单上所有按钮的手形光标。

这类似于我们在Web页面上使用CSS所做的操作(input[type=button] { cursor:pointer; }

2个回答

6
按照 @Madprogrammer 的建议,遍历树是在动态或特定形式上改变光标的方法。
仅供娱乐(并再次展示 SwingX :) - 如果您想全局安装该光标,然后不再关心它,请安装一个UI委托来处理它。在SwingX中,只需实现并插入自定义按钮扩展即可。副作用与其他答案相同(尽管无法像那样解决)。通常的缺点(当安装自定义UI代理时总是如此)是需要为所有LAF子类化和插入代理。
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());
}

我看到了这个错误:UIDefaults.getUI() 失败了:没有 ComponentUI 类。
对我来说很好理解 - 在向 UIManager 注册 ui 类时,需要使用完全限定的类名来实例化代理。
// 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");

通常,您会将不同的委托方放在LAF特定的子包中,而不是在插件本身中。但这只是一个例子 :-)


看起来是一个不错的方法,我实际上正在我的项目中使用swingx(sdk 1.6),但当我将它放在我的主类上时,我会得到这个错误:UIDefaults.getUI()失败:没有ComponentUI类用于:javax.swing.JButton [,0,0,0x0,invalid,alignmentX = 0.0,alignmentY = 0.0,border =,flags = 0,maximumSize =,minimumSize =,preferredSize =,defaultIcon =,disabledIcon =,disabledSelectedIcon =,margin = null,paintBorder = true,paintFocus = true,pressedIcon =,rolloverEnabled = false,rolloverIcon =,rolloverSelectedIcon =,selectedIcon =,text =,defaultCapable = true]。 - Juan Jimenez

5
基本上,您需要遍历容器和子容器...但要小心,有些看似按钮的东西会让您惊讶。
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);

        }

    }

}

这将有一个好的副作用:当你走进 JComboBox(以及其他组件)并改变它们下拉按钮的光标时,要小心哦 ;)


好的,我需要在每个表单上都调用它吗?有没有办法让它通用化? - Juan Jimenez
基本上,尽可能传递最高的容器,但除此之外,是的。 - MadProgrammer
如果您使用comp.getClass().equals(JButton.class)替换comp instanceof JButton,则将不再有副作用... - aymeric
@MadProgrammer 感谢您的建议,但这不是一个合适的解决方案,因为我有很多屏幕,并且不想在每个屏幕上调用此方法。我知道另一种方法是从基本JFrame或JButton类继承并应用光标,但我正在寻找更通用的解决方案。 - Juan Jimenez
@aymeric 当我应用你的建议时,我的按钮消失了。 - Juan Jimenez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接