单击按钮时为什么会出现相同的按钮?

时间:2016-10-01 20:57:25

标签: java swing jbutton

当我运行此代码时,“颜色”按钮将出现在左上角。当我拖动窗口时,按钮消失了。代码基本上有效,但我不知道会发生这种情况。每次点击它时都会出现按钮。

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

public class TrafficLightPanel extends JPanel implements ActionListener{
private JLabel changeColor;
private Color color;

public TrafficLightPanel(){
    setSize(new Dimension(300,200));    
    setPreferredSize (new Dimension(300, 200));
    color = color.RED;

}
public void paintComponent(Graphics g){
    g.setColor(color);
    g.fillOval(100,100,100,100);
}
public void setColor (Color shade)
{
    color = shade;
}
public void  createButton(){}
public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub

}
public static void main(String[] args){
    JFrame frame = new JFrame("Color Circle");
    JButton[] buttons = new JButton[3];
    String[] colors = new String[]{"RED", "GREEN", "BLUE"};
    TrafficLightPanel panel = new TrafficLightPanel()
    {
        @Override
        public void  createButton(){
            for(int i = 0; i < 3; i++)
            {
                // make new button name 

                buttons[i] = new JButton("" + colors[i]);
                if(i == 0)
                    buttons[i].addActionListener(this);
                else if(i == 1)
                    buttons[i].addActionListener(this);
                else if(i == 2)
                    buttons[i].addActionListener(this);

                add(buttons[i]);
                //System.out.println(buttons[i]);
            }
        }
        @Override
        public void actionPerformed(ActionEvent e) {
               if (e.getSource() == buttons[0]) {
                   setColor(Color.RED);
                    repaint();
               } else if (e.getSource() == buttons[1]) {
                   setColor(Color.GREEN);
                    repaint();
               }
               else if (e.getSource() == buttons[2]) {
                   setColor(Color.BLUE);
                    repaint();
                   }
            }

            };
            panel.createButton();   
    frame.getContentPane().add(panel);
    frame.pack();
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


}

}

1 个答案:

答案 0 :(得分:3)

你的paintComponent方法应首先调用super方法,以便JPanel执行其管家图形,其中包括删除所谓的&#34;脏&#34;像素。所以:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);  // *** add this ***
    g.setColor(color);
    g.fillOval(100, 100, 100, 100);
}

我自己,我做的事情有点不同,你可以考虑或不考虑一些建议:

  • 创建一个仅用于绘图的JPanel,没有其他内容,没有按钮,没有任何内容。
  • 将JButton放在不同的JPanel中。
  • 使用枚举(可能称为LightColor),用于将Color与String组合,以及在创建按钮时使用。
  • 在paintComponent方法中,将Graphics对象强制转换为Graphics2D对象,以便我们可以使用RenderingHints绘制更光滑的圆圈。
  • 避免设置任何尺寸。而是在需要的地方覆盖setPreferredSize,让应用程序的组件和布局管理器通过在创建它之后但在显示之前调用JFrame上的pack()来自行调整大小。

例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;

import javax.swing.*;

// main GUI JPanel that holds the light drawing JPanel as well as the buttons
@SuppressWarnings("serial")
public class TrafficLightPanel2 extends JPanel {
    private static final int LIGHT_SIZE = 200; // size of the circle
    private static final int GAP = 10; // border gap around the jpanel

    // the Jlight drawing JPanel that draws the circles
    private LightDrawingPanel lightDrawingPanel = new LightDrawingPanel(null, LIGHT_SIZE);

    public TrafficLightPanel2() {
        // JPanel to hold the buttons, 1 row, variable number of columns, gap between buttons
        JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
        for (LightColor lightColor : LightColor.values()) {
            // create each button within the loop, giving it an Action -- an ActionListener "on steroids"
            buttonPanel.add(new JButton(new LightColorAction(lightColor, lightDrawingPanel)));
        }

        setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        setLayout(new BorderLayout(GAP, GAP));
        add(lightDrawingPanel, BorderLayout.CENTER);  // add the light drawer to the center
        add(buttonPanel, BorderLayout.PAGE_END);  // and the buttons to the bottom
    }

    private static void createAndShowGui() {
        TrafficLightPanel2 mainPanel = new TrafficLightPanel2();

        JFrame frame = new JFrame("Traffic Light");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();  // have layout managers do their thing
        frame.setLocationRelativeTo(null); // center
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

// just acts as a class that connects a Color with a String
enum LightColor {
    RED(Color.RED, "Red"), YELLOW(Color.YELLOW, "Yellow"), GREEN(Color.GREEN, "Green");

    private LightColor(Color color, String text) {
        this.color = color;
        this.text = text;
    }
    private Color color;
    private String text;

    public Color getColor() {
        return color;
    }

    public String getText() {
        return text;
    }

    @Override
    public String toString() {
        return text;
    }
}

// create a class that only draws the circle, and that's it
@SuppressWarnings("serial")
class LightDrawingPanel extends JPanel {
    private Color color;
    private int size;

    public LightDrawingPanel(Color color, int size) {
        this.color = color;
        this.size = size;
    }

    public void setColor(Color color) {
        this.color = color;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);  // again, the super must be called

        // if no color defined, get out of here
        if (color == null) {
            return;
        }

        g.setColor(color);

        // make for smooth rendering 
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // center the circle
        int x = (getWidth() - size) / 2;
        int y = (getHeight() - size) / 2;
        g2.fillOval(x, y, size, size);
    }

    // make our JPanel at least as large as the circle
    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(size, size);
    }
}

// AbstractAction for our buttons
// like an ActionListener "on steroids"
@SuppressWarnings("serial")
class LightColorAction extends AbstractAction {
    private LightColor lightColor;
    private LightDrawingPanel lightDrawingPanel;

    public LightColorAction(LightColor lightColor, LightDrawingPanel lightDrawingPanel) {
        super(lightColor.getText());  // text for the button to show

        // initialize our fields
        this.lightColor = lightColor;
        this.lightDrawingPanel = lightDrawingPanel;

        // alt-key mnemonic derived from the text String
        int mnemonic = (int) lightColor.getText().charAt(0);
        putValue(MNEMONIC_KEY, mnemonic);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // set the color of the drawing panel
        lightDrawingPanel.setColor(lightColor.getColor());
    }
}