How to change the color of an individual ellipse when clicking a jButton?

社会主义新天地 提交于 2019-12-25 03:47:58

问题


I want to be able to click the JButton and change the next individual ellipse I make to its respective color, Red or Black, from its default Blue. So far I'm able to change the color of all the ellipses I have made.

public class MainClient {

private JFrame frame;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                MainClient window = new MainClient();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public MainClient() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
    private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 800, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    final SpriteField panel = new SpriteField();
    panel.setBounds(0, 110, 782, 331);
    panel.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            int tX = e.getX();
            int tY = e.getY();
            panel.CreateObjectAt(tX,tY);
        }
    });
    frame.getContentPane().setLayout(null);
    panel.setBackground(Color.LIGHT_GRAY);
    frame.getContentPane().add(panel);

    final JButton btnRed = new JButton("black");
    btnRed.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            panel.setColor(Color.BLACK);
        }
    });
    btnRed.setBounds(229, 500, 97, 25);
    frame.getContentPane().add(btnRed);

    JButton btnRed_1 = new JButton("red");
    btnRed_1.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            panel.setColor(Color.RED);
        }
    });
    btnRed_1.setBounds(342, 500, 97, 25);
    frame.getContentPane().add(btnRed_1);

}

}

I have a SriteField Class

public class SpriteField extends JPanel
{
    ArrayList<RoundSprite>mSprites = new ArrayList<RoundSprite>();

    private Color color = Color.BLUE;
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        AffineTransform tOldTransform = g2.getTransform();

        for(RoundSprite tOne:mSprites)
        {
            tOne.DrawSprite(g2, color);
        }
        g2.setTransform(tOldTransform);
    }
    public void CreateObjectAt(int tX, int tY)
    {
        //make sprite
        RoundSprite mLonely = new RoundSprite();
        //set position
        mLonely.SetPosition(tX, tY);
        //add to array
        mSprites.add(mLonely);
        repaint();
    }
    public void setColor(Color color)
    {
        this.color = color;
        repaint();
    }

}

I have a RoundSprite Class

public class RoundSprite 
{
int mX;
int mY;
private Color color;
void DrawSprite(Graphics2D g2, Color color)
{

    AffineTransform tOldTransform = g2.getTransform();
    g2.setColor(color);
    g2.translate(mX, mY); //got it out from the corner

    g2.draw(new Ellipse2D.Double(-15, -22, 30, 50));

    g2.setTransform(tOldTransform);

}
public void SetPosition(int tX, int tY) //g2.translate
{
    mX = tX;
    mY = tY;        
}

回答1:


There are three core issues...

One

In order for the panel_1 MouseListener to change the color of the sprites within panel, the MouseListener requires a reference to the panel.

You could declare the panel as final within the initialize method, but I prefer to make the panel a private instance field of the MainClient.

Two

In order to change the color, the SpriteField needs to provide a means by which interested parties can request a change.

This is going to require SpriteField to provide some kind of method that interested parties can call when they need to, for example, a setColor method...

public class SpriteField extends JPanel {

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

Then panel_1's MouseListener can now reference the SpriteField and call a method which can produce a change...

panel_1.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Click");
        panel.setColor(Color.BLUE);
    }
});

Three

You need some way to tell the sprite what color it should be...

This one depends on what it is you want to achieve...

If you want to paint ALL the sprites the same color, then you need some way to tell the sprites which color they should use, for example, you could change the DrawSprite method to accept a Color parameter...

public class RoundSprite {
    //...
    void DrawSprite(Graphics2D g2, Color color) {

And within the SpriteField paintComponent, pass the color to the sprite

public class SpriteField extends JPanel {
    //...
    private Color color = Color.BLACK;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        AffineTransform tOldTransform = g2.getTransform();


        for (RoundSprite tOne : mSprites) {
            tOne.DrawSprite(g2, color);
        }
        g2.setTransform(tOldTransform);
    }

Now, this will paint ALL the sprites within the field the same color, if you want to change the color of individual sprites, this comes infinitely more complicated...

Lets leave aside the issues of selecting a sprite for the moment...

Basically, you would need to apply the same principle from point Two to the RoundSprite class.

You would need to supply a method that could set/get the desired color. You would need to store this value in an instance field of the RoundSprite class and when DrawSprite is called, apply that Color to the Graphics context.

This would mean that SpriteField won't need to perform any color management, beyond passing the request for change from a caller to the selected sprite, so it would still need a setColor method...

Side Notes...

You might like to have a read through Code Conventions for the Java TM Programming Language, it will make it easier for people to read your code and for you to read others

Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

Oh, and you realise that there already is a JButton class that probably should be used instead of a JPanel with a MouseListener....?



来源:https://stackoverflow.com/questions/25110272/how-to-change-the-color-of-an-individual-ellipse-when-clicking-a-jbutton

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!