Цвет фона на панели не изменится


Следующий код создает окно с кнопками, но при запуске i и действительном нажатии кнопки появляется сообщение об ошибке. Согласно подсказке Spring tooltip:

Cannot make a static reference to the non-static method setBackground(Color) from the type JComponent

Эта программа буквально введена из моего учебника Java строка за строкой, насколько я могу судить. Это более старая книга, так что может быть несовместимость, но это не кажется вероятным.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ButtonTest
{
    public static void main(String[] args)
    {
        final ButtonFrame frame = new ButtonFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.show();
}
}

class ButtonFrame extends JFrame
{
    public ButtonFrame()
    {
    setTitle("Button Test");
    setSize(Default_width, Default_height);

        //panel
        ButtonPanel panel = new ButtonPanel();
        Container contentPane=getContentPane();
        contentPane.add(panel);
    }

    public static final int Default_width = 300;
public static final int Default_height = 200;
}

class ButtonPanel extends JPanel
{
public ButtonPanel()
{
    JButton yellowButton = new JButton("Yellow");
    JButton blueButton = new JButton("Blue");
    JButton redButton = new JButton("Red");

    add(yellowButton);
    add(blueButton);
    add(redButton);

    ColorAction yellowAction= new ColorAction(Color.YELLOW);
    ColorAction redAction = new ColorAction(Color.RED);
    ColorAction blueAction = new ColorAction(Color.BLUE);

    yellowButton.addActionListener(yellowAction);
    blueButton.addActionListener(blueAction);
    redButton.addActionListener(redAction);
    }
}

    class ColorAction implements ActionListener
    {
        public ColorAction(Color c)
    {
        backgroundColor=c;
    }

    public void actionPerformed(ActionEvent event)
    {
    ButtonPanel.setBackground(backgroundColor);
    }

        private Color backgroundColor;
}
3 3

3 ответа:

Один из подходов заключается в том, чтобы гнездо ColorAction как внутренний класс в ButtonPanel, где он имеет неявный доступ к заключающей панели.

Добавление: как отмечалось в комментариях @Andrew Thompson и @nachokk, неявная доступность может быть сделана явной путем квалификации this с использованием заключающего имени класса. Видишь JLS §15.8.4. Квалифицированный специалист this за подробностями. В этом примере эти два вызова эквивалентны:
 setBackground(backgroundColor);
 ButtonPanel.this.setBackground(backgroundColor);

Как более общее альтернативно, рассмотрим инкапсуляцию целевой панели и цвета в Action, как описано здесь.

изображение

class ButtonPanel extends JPanel {

    public ButtonPanel() {
        JButton yellowButton = new JButton("Yellow");
        JButton blueButton = new JButton("Blue");
        JButton redButton = new JButton("Red");

        add(yellowButton);
        add(blueButton);
        add(redButton);

        ColorAction yellowAction = new ColorAction(Color.YELLOW);
        ColorAction redAction = new ColorAction(Color.RED);
        ColorAction blueAction = new ColorAction(Color.BLUE);

        yellowButton.addActionListener(yellowAction);
        blueButton.addActionListener(blueAction);
        redButton.addActionListener(redAction);
    }

    private class ColorAction implements ActionListener {

        public ColorAction(Color c) {
            backgroundColor = c;
        }

         @Override
         public void actionPerformed(ActionEvent event) {
            setBackground(backgroundColor);
        }
        private Color backgroundColor;
    }
}

Панель кнопок.setBackground () это не статический метод, поэтому вы не можете вызвать его как один. Вам нужен конкретный экземпляр ButtonPanel, чтобы установить фон.

ButtonPanel bp = new ButtonPanel();
bp.setBackground(backgroundColor);

Также изменение внешнего вида может помочь:

//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());