Frage

I have to draw some ovals in Java, and at click to change their color. For the beginning I tried to change the color after 20 ms, but it doesn't work.

My code is:

public class MyComponentNew extends Frame {

    public Graphics2D g2d;

    public MyComponentNew(String title) {
        super(title);
        setSize(400, 550);
    }

    @Override
    public void paint(Graphics g) {
        this.g2d = (Graphics2D) g;

        this.g2d.setColor(Color.red);
        this.g2d.fillOval(10, 55, 50, 100);
    }

    public void changeColor () {        
        this.g2d.setColor(Color.blue);
        this.g2d.fillOval(10, 55, 50, 100);
    }
}

And in the class with main method I have:

MyComponentNew m;

m = new MyComponentNew("Fereastra cu baloane");
m.setVisible(true);

m.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosing(WindowEvent we) {
        System.exit(0);
    }
});

try {
    Thread.sleep(20);
} catch(InterruptedException e) {} 

m.changeColor();

The color of the oval remains red.

War es hilfreich?

Lösung

You need to look at Performing Custom Painting. You kinda have the concept, but your changeColor method isn't going to do anything for you.

Some things to note.

  • First you need to add a MouseListener. See more at How to Write MouseListeners

  • Second what you want to do is just have a Color color variable. You use that variable to set the color. Your method changeColor should only change the color and repaint(). Something like

    public class MyComponentNew extends JPanel {
        private Color color = Color.BLUE;
    
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(color);
        }
    
        public void changeColor() {
            if (color == Color.BLUE) {
                color = Color.RED:
            } else {
                color = color.BLUE;
            }
            repaint();
        }
    }
    
  • Third notice how I use JPanel instead of JFrame. This is the preferred approach.

  • Fourth you should be using Swing and not AWT.


Here's a full example, with those points above

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;

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

public class CircleChangeColor extends JPanel {
    private Ellipse2D circle = new Ellipse2D.Double(0, 0, 200, 200);
    private Color color = Color.blue;

    public CircleChangeColor() {
        addMouseListener(new MouseAdapter(){
            public void mousePressed(MouseEvent e) {
                if (circle.contains(e.getPoint())) {
                    changeColor();
                }
            }
        });
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setColor(color);
        g2.fill(circle);
    }

    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    public void changeColor() {
        if (color == Color.BLUE) {
            color = Color.RED;
        } else {
            color = color.BLUE;
        }
        repaint();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new CircleChangeColor());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            }
        });

    }
}

Andere Tipps

The reason is that your paint method will be called periodically by AWT and it will quickly draw over your new blue oval with the original red one. You can get the behavior you want by storing the oval color in a member variable, reading it in the paint method, and changing it in your changeColor method.

public class MyComponentNew extends Frame {

    private Color ovalColor;

    public MyComponentNew(String title) {
        super(title);
        setSize(400, 550);
        ovalColor = Color.red; // initial oval color
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;

        g2d.setColor(ovalColor); // use whatever the current color is
        g2d.fillOval(10, 55, 50, 100);
    }

    public void changeColor() {    
        ovalColor = Color.blue; // change color
        repaint(); // force redraw with new color
    }
}

You need to call the repaint() method on the JFrame, but as the code is, the red oval will be drawn again since the paint-method will be called. You need to alter it something like this:

import java.awt.Graphics2D;

public class MyComponentNew extends Frame{

    public Graphics2D g2d;
    public Color color = Color.red;

    public MyComponentNew(String title) {
        super(title);
        setSize(400, 550);

    }

    @Override
    public void paint(Graphics g) {
        this.g2d = (Graphics2D) g;
        this.g2d.setColor(color);
        this.g2d.fillOval(10, 55, 50, 100);
        //this.g2d.drawLine (WIDTH, WIDTH, WIDTH, WIDTH);
    }

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

The color is now an instance variable which is set during the changeColor method.

/Nick

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top