Java - zmiana koloru przycisku przy kliknięciu nie działa poprawnie

0

Cześć. Mam problem ze zmianą koloru przycisku.

Kiedy przycisk jest w kliknięty zmienia kolor który nie jest zawarty w moim kodzie, ale kiedy (trzymając w kliknięty przycisk na myszce) przesunę kursor poza obszar przycisku, zmienia kolor na zdefiniowany w kodzie.

Do zmiany koloru przycisku używam metody ChangeListener.

btn1.getModel().addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) {
        ButtonModel model = (ButtonModel) e.getSource();

        if (model.isRollover()) {
            btn1.setBackground(new Color(166,166, 166));
        } else if (model.isPressed()) {
            btn1.setBackground(new Color(255, 64, 0));
        } else {
            btn1.setBackground(new Color(201, 201, 201));
        }
    }
});

A tutaj screen shot z wykonania tego kodu, po kolei:

  1. oryginał
  2. po najechaniu
  3. w kliknięty (tu występuje błąd)
  4. w kliknięty i kursor przesunięty poza obszar przycisku.

user image

2

To nie jest błąd. Po prostu podczas kliknięcia taki kolor (rgb 184, 207, 229) domyślnie przyjmuje tło JButton'a z uwagi m.in. na posiadany "focus", ale też po prostu na to, jak jest zaimplementowany DefaultButtonModel. Niestety użycie JButton.setFocusable(false) pod inicjalizacją obiektu nie ratuje nas z beznadziejnej sytuacji. Można by pomyśleć o nadpisaniu metody interfejsu MouseAdapter dla metody JButton'a addMouseListener, tj. metody mousePressed, i zawarciu tutaj JButton.setFocusable(false):

 
JButton.addMouseListener(new MouseAdapter() {

    @Override
    public void mousePressed(MouseEvent e) {
    	JButton.setFocusable(false);
        JButton.setBackground(new Color(255, 243, 0));
    }
}

...ale niestety działa to jedynie przy pierwszym kliknięciu (przynajmniej u mnie). Czy więc się nie da? Da. Paradoksalnie wykorzystując we właściwy sposób model dla JButtona. Mianowicie musimy rozszerzyć klasę DefaultButtonModel i nadpisać metodę isPressed():

public class CoolButtonModel extends DefaultButtonModel {

    @Override
    public boolean isPressed() {
        return false;
    }
}

Teraz tworzymy już klasę testową i sprawdzamy nasze rozwiązanie:

public class Test extends JFrame {

    public Test() {
        init();
    }

    private void init() {

        // Set JFrame characteristics.
        setTitle("Button example");
        setSize(300, 300);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        // Create button etc.
        JButton button = new JButton("Test");
        button.setModel(new CoolButtonModel());

        button.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                button.setBackground(new Color(255, 243, 0));
            }
            

            @Override
            public void mouseReleased(MouseEvent e) {
                button.setBackground(new Color(255, 64, 0));
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                button.setBackground(new Color(166, 166, 166));
            }

            @Override
            public void mouseExited(MouseEvent e) {
                button.setBackground(null);
            }
        });

        add(button);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            Test window = new Test();
            window.setVisible(true);
        });
    }
}

No i wszystko działa jak należy. Teraz, gdy będziesz najeżdżał kursorem na przycisk lub tym kursorem uciekał poza pole przycisku, przycisk będzie zmieniał kolor. Zmieni kolor również wtedy, gdy naciśniesz przycisk myszy, a także zmieni kolor, gdy ten przycisk puścisz.

Oczywiście, to nie jest jedyne rozwiązanie problemu.

0

A tak w ogóle to polecam JavaFX.
Imho nie warto inwestować czas w zagłębianie Swing'a.

1 użytkowników online, w tym zalogowanych: 0, gości: 1