Предотвратить JButton repaint () после нажатия - PullRequest
0 голосов
/ 26 апреля 2020

У меня есть кнопка. Я хочу изменить фон после того, как нажму на него. Моя проблема здесь - кнопка автоматического вызова paintComponent(). Как можно предотвратить это? Я ожидаю, что после нажатия кнопки кнопка будет синей, но она по-прежнему будет красной.

package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonDemo extends JButton implements ActionListener{

    public ButtonDemo() {
        this.setText("BUTTON TEXT");
        this.addActionListener(this);
    }
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        setBackground(Color.RED);
    }
    public static void main(String[] args){
        JFrame frame = new JFrame();
        JPanel contentPane = new JPanel();
        frame.setContentPane(contentPane);
        contentPane.add(new ButtonDemo());
        frame.setSize(500, 500);

        frame.setVisible(true);

    }
    @Override
    public void actionPerformed(ActionEvent e) {
        this.setBackground(Color.BLUE);
    }  
}

Ответы [ 3 ]

2 голосов
/ 26 апреля 2020

По моему личному интуитивному ощущению JButton, вероятно, не подходит для вашей желаемой цели.

По сути, вы хотите контролировать, когда и как изменяется "выбранное" состояние пьесы.

Лично у меня был бы какой-то контроллер, который каким-то образом отслеживал бы события мыши (возможно, компонент штук делегирует событие обратно контроллеру) и какая-то модель, которая контролирует, когда куски становятся выбранными, это затем уведомляло бы контроллер изменения состояния, и он будет делать соответствующие обновления пользовательского интерфейса.

Но это долгий процесс настройки. Вместо этого я демонстрирую простую концепцию, где компонент может быть выбран с помощью мыши, но только контроллер может отменить выбор. В этом примере это позволит выбрать только один кусок

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridLayout(5, 5));

            ChangeListener listener = new ChangeListener() {
                private PiecePane selectedPiece;

                @Override
                public void stateChanged(ChangeEvent e) {
                    if (!(e.getSource() instanceof PiecePane)) { return; }

                    PiecePane piece = (PiecePane) e.getSource();

                    // Want to ignore events from the selected piece, as this
                    // might interfer with the changing of the pieces
                    if (selectedPiece == piece) { return; }

                    if (selectedPiece != null) {
                        selectedPiece.setSelecetd(false);
                        selectedPiece = null;
                    }

                    selectedPiece = piece;
                }
            };

            for (int index = 0; index < 5 * 5; index++) {
                PiecePane pane = new PiecePane();
                pane.addChangeListener(listener);
                add(pane);
            }
        }

    }

    public class PiecePane extends JPanel {

        private boolean selecetd;
        private Color selectedBackground;
        private Color normalBackground;

        private MouseListener mouseListener;

        public PiecePane() {
            setBorder(new LineBorder(Color.DARK_GRAY));
            mouseListener = new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    setSelecetd(true);
                }
            };

            setNormalBackground(Color.BLUE);
            setSelectedBackground(Color.RED);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(50, 50);
        }

        @Override
        public void addNotify() {
            super.addNotify(); 
            addMouseListener(mouseListener);
        }

        @Override
        public void removeNotify() {
            super.removeNotify(); 
            removeMouseListener(mouseListener);
        }

        public void addChangeListener(ChangeListener listener) {
            listenerList.add(ChangeListener.class, listener);
        }

        public void removeChangeListener(ChangeListener listener) {
            listenerList.remove(ChangeListener.class, listener);
        }

        protected void fireSelectionChanged() {
            ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
            if (listeners.length == 0) {
                return;
            }
            ChangeEvent evt = new ChangeEvent(this);
            for (int index = listeners.length - 1; index >= 0; index--) {
                listeners[index].stateChanged(evt);
            }
        }

        public boolean isSelected() {
            return selecetd;
        }

        public void setSelecetd(boolean selecetd) {
            if (selecetd == this.selecetd) { return; }
            this.selecetd = selecetd;
            updateSelectedState();
            fireSelectionChanged();
        }

        public Color getSelectedBackground() {
            return selectedBackground;
        }

        public void setSelectedBackground(Color selectedBackground) {
            this.selectedBackground = selectedBackground;
            updateSelectedState();
        }

        public Color getNormalBackground() {
            return normalBackground;
        }

        public void setNormalBackground(Color normalBackground) {
            this.normalBackground = normalBackground;
            updateSelectedState();
        }

        protected void updateSelectedState() {
            if (isSelected()) {
                setBackground(getSelectedBackground());
            } else {
                setBackground(getNormalBackground());
            }
        }
    }
}
1 голос
/ 26 апреля 2020

Я создал кнопку переключения.

Вы устанавливаете основной цвет и альтернативный цвет в конструкторе класса.

Когда вы вызываете метод switchColors, фон JButton изменяется от основного цвета до альтернативного цвета. При повторном вызове метода switchColors фон JButton меняется с альтернативного цвета на основной.

В следующем примере я поместил метод switchColors в actionListener, чтобы вы могли видеть изменение цвета. Каждый раз, когда вы щелкаете левой кнопкой мыши на кнопке JButton, цвет фона меняется.

Вы вызываете метод switchColors, когда хотите, чтобы фон JButton изменил цвет с синего на красный, и снова, когда вы хотите, чтобы JButton фон изменится с красного на синий. Это под вашим контролем.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ButtonDemo extends JButton 
        implements ActionListener {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Button Demo");
                frame.setDefaultCloseOperation(
                        JFrame.EXIT_ON_CLOSE);
                JPanel contentPane = new JPanel();
                contentPane.setLayout(new BorderLayout());
                frame.setContentPane(contentPane);
                contentPane.add(new ButtonDemo(Color.BLUE, 
                        Color.RED));
                frame.setSize(300, 300);
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }

    private boolean primaryBackground;

    private Color primaryColor;
    private Color alternateColor;

    public ButtonDemo(Color primaryColor, 
            Color alternateColor) {
        this.primaryColor = primaryColor;
        this.alternateColor = alternateColor;
        this.primaryBackground = true;

        this.setText("BUTTON TEXT");
        this.setBackground(primaryColor);
        this.addActionListener(this);
    }

    public void switchColors() {
        primaryBackground = !primaryBackground;
        Color color = primaryBackground ? primaryColor :
            alternateColor;
        this.setBackground(color);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        switchColors();
    }

}
0 голосов
/ 26 апреля 2020

Если вы хотите ненадолго поменять фон, вы можете сделать это с помощью swing Timer:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class ButtonDemo extends JButton implements ActionListener{

    private static final int DELAY = 600; //milliseconds
    private final Timer timer;

    public ButtonDemo() {
        this.setText("BUTTON TEXT");
        this.addActionListener(this);
        Color defaultCloor = getBackground();
        timer = new Timer(DELAY, e-> setBackground(defaultCloor));
        timer.setRepeats(false);
    }

    public static void main(String[] args){
        JFrame frame = new JFrame();
        JPanel contentPane = new JPanel();
        frame.setContentPane(contentPane);
        contentPane.add(new ButtonDemo());
        frame.setSize(300, 200);
        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        timer.stop();
        this.setBackground(Color.RED);
        timer.start();
    }
}
...