繁体   English   中英

单击后防止 JButton repaint()

[英]Prevent JButton repaint() after click

我有一个按钮。 我想在点击后更改背景。 我的问题是按钮自动调用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);
    }  
}

我个人的直觉是JButton可能不适合您想要的目标。

从本质上讲,您想要控制何时以及如何更改工件的“选定”state。

就个人而言,我会有某种 controller 以某种方式监视鼠标事件(可能让片段组件将事件委托给控制器)和某种 model 控制何时选择片段,这将通知 Z5903C18ABA03F2C03E4E state 更改,它将对 UI 进行适当的更新。

但这是一个漫长的设置过程。 相反,我展示了一个简单的概念,其中可以使用鼠标选择组件,但只有 controller 可以取消选择。 在此示例中,这将只允许选择单件

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());
            }
        }
    }
}

我创建了一个切换按钮。

在 class 构造函数中设置原色和备用颜色。

当您调用switchColors方法时, JButton背景会从主要颜色变为备用颜色。 当您再次调用switchColors方法时, JButton背景会从备用颜色变为主颜色。

在下面的示例中,我将switchColors方法放在 actionListener 中,以便您可以看到颜色的变化。 每次左键单击 JButton,背景颜色都会改变。

当您希望JButton背景从蓝色变为红色时,您将调用switchColors方法,并且当您希望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();
    }

}

如果您想暂时更改背景,可以使用 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();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM