Изменение цвета фона выбранного JToggleButton

Я пытаюсь изменить цвет JToggleButton когда он был выбран в надежном, посмотрите и почувствуйте независимый путь.

если используется металлический L&F, то использование UIManager-это подход:

UIManager.put("ToggleButton.selected", Color.RED);

Примечание: Iyy указал, что у меня была опечатка в имени свойства выше, но я оставлю ее выше для людей, которые сюда попадают, но фактическое имя свойства должно быть:

UIManager.put("ToggleButton.select", Color.RED);

однако это не работает в моем текущий внешний вид (в настоящее время Windows XP). После некоторого дальнейшего анализа, похоже, что внешний вид системы в Windows (все еще XP) не использует ни одного из Colorна основе UIManager свойства ToggleButton вообще, или он, по крайней мере, не поставляет их сам (есть быстрый пример онлайн найти все ключи собственность от UIManager, который в Примере удобно ограничен явно Color свойства).

Я попытался установить фон цвет:

Action action = new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) { /* stuff */ }
};
JToggleButton button = new JToggleButton(action);
// tried with and without opaque true
button.setOpaque(true);
button.setBackground(Color.RED);

он не только не изменяет выбранное состояние, но даже не влияет на невыбранное состояние.

Я попытался изменить цвет фона только после получения действия:

@Override
public void actionPerformed(ActionEvent e)
{
    JToggleButton button = (JToggleButton)e.getSource();
    if (button.isSelected()) // alternatively, (Boolean)getValue(Action.SELECTED_KEY)
    {
        button.setBackground(Color.RED);
    }
}

не работает. Единственное, что я нашел для работы, требует, чтобы я сам нарисовал кнопку в выбранном состоянии (что приводит к рабочему примеру, хотя и нестандартному):

private class ColoredToggleButton extends JToggleButton
{
    ColoredToggleButton(Action action, Color color)
    {
        super(action);

        setBackground(color);
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if (this.isSelected())
        {
            int w = getWidth();
            int h = getHeight();
            String s = getText();

            // selected color
            g.setColor(getBackground());
            g.fillRect(0, 0, w, h);
            // selected foreground color
            g.setColor(SystemColor.controlText);
            g.drawString(s,
                         (w - g.getFontMetrics().stringWidth(s)) / 2 + 1,
                         (h + g.getFontMetrics().getAscent()) / 2 - 1);
        }
    }
}

это немного изменено из комментария в this отчет об ошибке Java. Интересно (забавно?), в претензии, были зафиксированы в 1998 году.

кто-нибудь знает лучший, независимый от L&F способ установить цвет фона выбранного JToggleButton?

5 ответов


вы можете увидеть, если setIcon() достаточно для вашей цели, но вы также можете переопределить paint() на ButtonUI делегат.

дополнение: комментарий @Клеопатра хорошо снято: изменение делегат UI не тривиально. последние @mKorbel это пример показывает как сложность, так и универсальность подхода. Его существенное преимущество-это взгляд и чувство независимости.

некоторые менее амбициозные подходы упоминаются здесь.


"выключатель.выбрано "неправильно, это требует" ToggleButton.выбирать." И должно быть обновление для компонента.

UIManager.put("ToggleButton.select", Color.WHITE);
SwingUtilities.updateComponentTreeUI(togglebuttonname);

JToggleButton btn = new JToggleButton(...);
btn.setUI(new MetalToggleButtonUI() {
    @Override
    protected Color getSelectColor() {
        return Color.RED;
    }
});

вы можете просто заставить цвет фона перед каждой перекраской - для этого вам нужно изменить paintComponent, проверить, включена ли кнопка, Установить фон в зависимости от состояния переключения и, наконец, позволить супер классу выполнить фактическую работу с краской:

public class ColoredToggleButton extends JToggleButton
{
    @Override
    public void paintComponent(Graphics g)
    {
        Color bg;
        if (isSelected()){
            bg = Color.GREEN;
        } else {
            bg = Color.RED;
        }
        setBackground(bg);
        super.paintComponent(g);
    }
}

Если вы предпочитаете использовать прослушиватель действий вместо переопределения методов в интерфейс, вы можете просто сменить интерфейс на интерфейс без каких-либо selectColor свойства.

вот пример, который я использовал недавно

private class FavouriteToggle extends JToggleButton {
    public FavouriteToggle() {
        setUI(new BasicToggleButtonUI()); //Removes selectColor

        ////Your Custom L&F Settings////
        setBackground(new Color(255, 252, 92));
        setForeground(Color.GRAY);
        setText("Favourite");
        setBorder(null);
        setFocusPainted(false);

        ////Add your own select color by setting background////
        addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(((JToggleButton) e.getSource()).isSelected()) {
                    setForeground(Color.BLACK);
                    setBackground(new Color(255, 251, 0));
                } else {
                    setBackground(new Color(255, 252, 92));
                    setForeground(Color.GRAY);
                }
            }
        });
    }
}