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

Java - zmiana koloru przycisku przy kliknięciu nie działa poprawnie
G9
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:39
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.

Kopiuj
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

Gjorni
  • Rejestracja:około 12 lat
  • Ostatnio:około 3 lata
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):

Kopiuj
 
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():

Kopiuj
public class CoolButtonModel extends DefaultButtonModel {

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

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

Kopiuj
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.


The quieter you become, the more you are able to hear.
G9
Dziękuję za tak obszerna odpowiedź ;)
Gjorni
Nie ma za co. Powodzenia w kodzeniu.
Fantazjatyk
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 3 lata
  • Postów:133
0

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

edytowany 2x, ostatnio: Fantazjatyk
Gjorni
Punkt widzenia zależy od punktu patrzenia. Jest wiele firm i instytucji, które stworzyły ogromne systemy, gdy Swing był jedynym słusznym wyborem w kontekście Javy. Takie oprogramowanie dalej musi być rozwijane, ale nieopłacalnym byłoby na razie refaktoryzowanie całego kodu pod JavaFX. Fakt, jest super, ale Swing też się może przydać w pracy.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.