Reputation: 41
i thought it would be easy to create a little programm with java :
so what i have done:
then something shocking happened: i clicked into my jFrame... nothing happened. i thought : ok let's make a repaint after creating the new circle... but it happened nothing! only if i click on the windwos Border and restretch it it "repaints" it.
what also ist really bad and sad, at the same time, is that if i click at a position and then at another position , and then restretch the frame, it only paints the last circle :( it should paint both! )
now i put repaint() on thousand different places but there was no difference. I also tried something with setopaque etc. just because i didnt know what to do at this point!
Here the mouseListener: you can ignore the color
public class Aufgabe3 {
public static Circ.CircleColor actualColor = CircleColor.ROT;
// fromone color to another depend on the actual
public static Circ.CircleColor getNextColor(Circ.CircleColor aktuell) {
switch (aktuell) {
case ROT:
return Circ.CircleColor.GRÜN;
case GRÜN:
return Circ.CircleColor.GELB;
case GELB:
return Circ.CircleColor.ROT;
default:
return null;
}
}
public static void main(String[] args) {
JFrame jFrame = new JFrame();
jFrame.setVisible(true);
jFrame.setSize(500, 500);
jFrame.setDefaultCloseOperation(jFrame.EXIT_ON_CLOSE);
// jFrame.add()
// farbenfolge rot,grün,gelb--
jFrame.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("clicked");
int x = e.getX();
int y = e.getY();
System.out.println("coords:" + x + "|" + y);
Circ circ = new Circ(x, y, actualColor);
circ.repaint();
jFrame.add(circ);
jFrame.repaint();
System.out.println(actualColor);
// actualisation of the next color
actualColor = getNextColor(actualColor);
}
});
}
}
and now the circle :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class Circ extends JComponent {
static public enum CircleColor {
ROT, GRÜN, GELB
};
private int x;
private int y;
private CircleColor circleColor;
public Circ() {
super();
}
public Circ(int x, int y, CircleColor circColor) {
super();
this.x = x;
this.y = y;
this.circleColor = circColor;
System.out.println("new circle created");
setSize(new Dimension(50, 50));
setVisible(true);
setOpaque(true);
}
public Color decodeCircleColor(CircleColor farbe) {
switch (farbe) {
case GRÜN:
return Color.GREEN;
case GELB:
return Color.yellow;
case ROT:
return Color.red;
default:
return null;
}
}
@Override
protected void paintComponent(Graphics g) {
System.out.println("paint");
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g2d);
g2d.setColor(decodeCircleColor(circleColor));
// g2d.drawOval(x, y, 50, 50);
g2d.fillOval(x, y, 50, 50);
}
}
Upvotes: 0
Views: 618
Reputation: 11949
If you add your component in a mouseClicked
event, that's probably revalidate that you should call because you change the container (the JFrame
). Also, JFrame are special: they have a content pane and you should add component this way:
frame.getContentPane().add(...);
The default content pane use a BorderLayout
.
Adding a component for each click is probably overkill and you'll have problem with layout unless you set it to null
(eg: the absolute layout) and call setBounds(x, y, 50, 50) for each circle.
However, since you overrides paintComponent
you may directly draw the ovals and not care about layout or components.
Add the Circle
component once, with a BorderLayout.CENTER constraints. This will ensure your Circle
will get the max size it can.
The MouseListener
should be on the Circle and you'll have to make it focusable (setFocus(true)
).
Each time the mouse is clicked on the Circle
, register the mouse position in a list (eg: List<Point>
) and then call repaint:
circle.points.add(new Point(e.getX(), e.getY()); //
circle.repaint();
Each time paintComponent(Graphics)
is called, use the list to draw the ovals in the order their were called.
@Override
protected void paintComponent(Graphics g) {
System.out.println("paint");
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g2d);
g2d.setColor(decodeCircleColor(circleColor));
// if you know lambda
points.forEach(p -> g2d.fillOval(p.x, p.y, 50, 50));
// or if you don't know lambda yet.
// for (Point p : points) g2d.fillOval(p.x, p.y, 50, 50));
}
Note that you may use a Point or any relevant class (for example, you may use a concrete object which would store a Paint
object such as java.awt.Color
to change the oval' color).
Upvotes: 0
Reputation: 22474
The default layout of a JFrame
is BorderLayout
.
When adding components to a BorderLayout
without specifying a position, they are added to the BorderLayout.CENTER
replacing the previous one set to this position.
That means that you always have only one Circle
added to your JFrame.
In any case, it looks like you're trying to draw circles at the cursor's position which means that you'll have to add the Circle
components to the JFrame
at different positions which is not that easy.
Instead of that, you're better off adding just one component to the frame and drawing all the circles in that component.
Upvotes: 1