I'm trying to make a map editor that supports rectangles in different angles (so it draws rectangles using polygons). I want to catch a polygon by their location on the frame without using mathematical calculations.
Is there a command supports such thing?
I tried to catch polygons by their visual representations:
public void mousePressed(MouseEvent e){
Component component = getComponentAt(e.getX(), e.getY());
if(component instanceof wall){
but it doesn't work.
(If i was simply drawing rectangles i would use JPanel and use setbounds command to draw a rectangle, but i dont think i can make polygon-shaped JPanels)
You first need to create a List containing all the Polygons you want to paint:
Shape circle = new Ellipse2D.Double(0, 0, 30, 30);
List<Shape> shapes = new ArrayList<Shape>();
shapes.add( circle );
Then in your paintComponent() method you iterate through all the shapes in the List:
Graphics2D g2d = (Graphics2D)g.create();
for (Shape shape : shapes)
{
g2d.draw( shape );
}
g2d.dispose();
Then in the MouseListener you iterate through the List to see which Shape was clicked:
public void mousePressed(MouseEvent e)
{
for (Shape shape : shapes)
{
if (shape.contains(e.getPoint())
// do something
}
}
If i was simply drawing rectangles i would use JPanel and use setbounds command to draw a rectangle, but i dont think i can make polygon-shaped JPanels
For an alternative approach that does use a component check out Playing With Shapes. The classes there allow you to create a ShapeComponent by using any Shape.
You wouldn't use individual JPanels to draw each Polygon. You would use a single class that extends JPanel, then overrides the paintComponent() method to draw the Polygons. More info here.
Once you've drawn your Polygons to the JPanel, you can use the Polygon.contains() method to test whether the mouse was inside a JPanel. More info on that in the API.
Related
I have an array with multiple Grapics2D Objects and want to draw all of them in a Panel. Its not drawing anything. Does anyone know how to fix this?
for (Graphics2D g2d : models) {
myPanel.paint(g2d);
}
I needed to draw a Car using Java and Graphics2D. I used multiple basicstrokes to come up with the shape of the car. How do I fill it with color? An example would be drawing 3 lines in the shape of a triangle and then wanting to fill it with color.
You can not simply fill a shape that was only created by drawing three lines. You have to define the shape, including all the lines that it consists of.
How exactly this is implemented depends on serveal factors. For example, whether you want to use the same stroke for all three lines, or whether they need different strokes.
It could be helpful if you had already provided some information of how exactly you are drawing the lines at the moment. I'll try to make a guess here...
So assuming that your current code roughly looks like this:
void paintCar(Graphics2D g)
{
g.setStroke(new BasicStroke(1.0f));
g.setColor(Color.BLUE);
// Draw the triangle
g.drawLine(100,100,200,100);
g.drawLine(100,200,150, 50);
g.drawLine(150, 50,100,100);
}
the easiest way to additionally fill this triangle would be to change it as follows:
void paintCar(Graphics2D g)
{
g.setStroke(new BasicStroke(1.0f));
g.setColor(Color.BLUE);
Path2D path = new Path2D();
// Build the triangle
path.append(new Line2D.Double(100,100,200,100), false);
path.append(new Line2D.Double(100,200,150, 50), true);
path.append(new Line2D.Double(150, 50,100,100), true);
// Draw the triangle
g.draw(path);
// Fill the triangle, with a different color
g.setColor(Color.CYAN);
g.fill(path);
}
But note...
... that there are more elegant and concise ways of achieving this. Usually, one would not append individual Line2D segments, but simply use the Path2D to build the shape:
void paintCar(Graphics2D g)
{
g.setStroke(new BasicStroke(1.0f));
g.setColor(Color.BLUE);
// Build the triangle
Path2D path = new Path2D();
path.moveTo(100,100);
path.lineTo(200,100);
path.lineTo(150, 50);
path.closePath();
// Draw the triangle
g.draw(path);
// Fill the triangle, with a different color
g.setColor(Color.CYAN);
g.fill(path);
}
So if you have the coordinates of your shape in an appropriate form (maybe stored as a list of Point2D objects), you may more easily build a shape that you can draw and fill then.
Ok dear folks, i've got this question and i don't really know a certain way to solve it.
I'm doing like a "Paint application" in java, i know everything is ready, but I need to paint the shapes with Computer Graphics Algorithms.
So, the thing is, once the shape is painted in the container how could I convert it like sort of an "Object" to be able to select the shape and move it around (I have to move it with another algorithm) I just want to know how could I know that some random point clicked in the screen belongs to an object, knowing that, I would be able to fill it(with algorithm).
I was thinking that having a Point class, and a shape class, if i click on the screen, get the coordinates and look within all the shapes and their points, but this may not be very efficient.
Any ideas guys ?
Thanks for the help.
Here is some of my code:
public class Windows extends JFrame{
private JPanel panel;
private JLabel etiqueta,etiqueta2;
public Windows() {
initcomp();
}
public void initcomp()
{
panel = new JPanel();
panel.setBounds(50, 50, 300, 300);
etiqueta = new JLabel("Circulo Trigonometrico");
etiqueta.setBounds(20, 40, 200, 30);
etiqueta2 = new JLabel("Circulo Bresenham");
etiqueta2.setBounds(150, 110, 200, 30);
panel.setLayout(null);
panel.add(etiqueta);
panel.add(etiqueta2);
panel.setBackground(Color.gray);
this.add(panel);
this.setLayout(null);
this.setVisible(true);
this.setSize(400,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
g2d.setStroke(new BasicStroke(2));
dibujarCirculo_bresenham(g2d, 50, 260, 260);
dibujarCirculo_trigonometrico(g2d, 50, 130, 200);
}
/*This functions paints a Circle*/
public void dibujarCirculo_trigonometrico(Graphics g,int R,int xc,int yc)
{
int x,y;
for (int i = 0; i < 180; i++) {
double angulo = Math.toRadians(i);
x = (int) (Math.cos(angulo)*R);
y = (int) (Math.sin(angulo)*R);
g.drawLine(x+xc, y+yc, x+xc, y+yc);
g.drawLine((-x+xc), (-y+yc), (-x+xc), (-y+yc));
}
}
I assume that any image is a valid (isn't constrained to a particular set of shapes). To get an contiguous area with similar properties, try using a flood fill.
To colour in or move a particular shape around, you can use flood fill to determine the set of pixels and manipulate the set accordingly. You can set a tolerance for similar hue, etc so that it's not as rigid as in Paint, and becomes more like the magic selection tool in Photoshop.
There are a couple of approaches to take here depending on what precisely you want.
1) is to have objects, one for each drawn thing on screen, with classes like Circle and Rectangle and Polygon so on. They would define methods like paint (how to draw them on screen), isCLickInsideOf (is a click at this point on screen contained by this shape, given size/position/etc?) and so on. Then, to redraw the screen draw each object, and to test if an object is being clicked on ask each object what it thinks.
2) is, if objects have the property of being uniform in colour, you can grab all pixels that make up a shape when the user clicks on one of the pixels by using a floodfill algorithm. Then you can load these into some kind of data structure, move them around as the user moves the mouse around, etc. Also, if every object is guaranteed to have a unique colour, you can test which object is being clicked on by just looking at colour. (Libraries like OpenGL use a trick like this sometimes to determine what object you have clicked on - drawing each object as a flat colour on a hidden frame and testing what pixel colour under the mouse pointer is)
What I want to achieve is something like this:
public void paint(Graphics g) {
Graphics2D ga = (Graphics2D) g;
MyShape c = new MyShape();
ga.draw(c);
}
I want that MyShape class to contain the info required to draw a circle with a number inside it.
So, I guess I need to create some kind of container/component, and drew what I need (the circle and the number) inside it, and then pass it further to the method I've pasted above.
The problem is I don't know what class to extend ... and the rest of the story.
A Shape is just that: a shape. A circle is a shape. A rectangle is a shape. But a circle with a number inside it is not a shape. My guess is that you in fact want something like this:
public class CircleWithNumberInside extends JComponent {
#Override
protected void paintComponent(Graphics g) {
// TODO draw a circle, and draw a number inside it.
}
}
You can certainly implement the Shape interface yourself, but there's no need when you can use an existing subclass, such as Ellipse2D. Just construct it with the same value for width and height. There's an example here that shows how to center an arbitrary glyph in an Ellipse2D.Double.
You have to extend the class Shape, which inside you would have to override the paintComponent so that the Graphics2D object knows what to draw.
This is my second semester doing Java and so please be patient. Part of my assignment is to click a Radio button and use the Circle's draw method to draw a Circle object on a Jpanel Content pane when the mouse button is clicked. Then store each Circle object in a Arraylist so that it will stay on the pane until I unclick the radio button. I can get everything to work except for adding the Circle object to the Arraylist and keeping that circle on the screen. It will just draw one circle at a time and erase the first previous one when I click again. I don't think that I am adding the new circles created to the Arraylist, I'm just a circle. Not sure.
Here is my code for the part that is drawing the circle.
public class MyPanel extends JPanel {
public ArrayList<Circle> circles;
public void paintComponent(Graphics g) {
Circle c = new Circle(xstart, ystart); //create a new circle
ArrayList<Circle> circles = new ArrayList<Circle>();
if (drawing){
c.draw(g);
circles.add(c);
for(int k=0; k<circles.size(); k++){
circles.get(k).draw(g);
}
} // draw the circle
Code for drawing and declaring the drawing boolean in my MouseTest Constructor and tied to the radio button. Drawing true means that when the radio button is clicked then it can draw circles.
JPanel radioPanel = new JPanel(new GridLayout(2,0)); //new GridLayout(y, x)
radioPanel.add(circleButton);
radioPanel.add(trackButton);
cp.add(radioPanel,BorderLayout.EAST);
drawing = false;
circleButton.addActionListener(new ActionListener() {
//Set drawing to true when the button is clicked
public void actionPerformed(ActionEvent ae) {
drawCircles();
}
});
public void drawCircles() { //initialize tracking to false
drawing = !drawing;`
You have a couple of issues. First, in your paintComponent function you are creating a local ArrayList of Circles. Each time the paintComponent is called, you are recreating this variable. Instead, just use the ArrayList of Circles that belongs to the class.
The other issue you have is that each circle is being drawn twice, once after the circle is created, the other time in the for loop. you should remove the call to have the circle draw itself, and just drawn them all in the for loop.
Finally, and this may or may not be the desired behavior, but currently you are creating a new Circle each time the paintComponent is getting called. You can potentially end up with many more circles than you want, because this function can be called a lot. You may want to reconsider at what point new circles are being created.
The following fixes the first couple of issues.
public class MyPanel extends JPanel {
public ArrayList<Circle> circles = new ArrayList<Circle>();
public void paintComponent(Graphics g) {
Circle c = new Circle(xstart, ystart); //create a new circle
circles.add(c);
if (drawing){
for(int k=0; k<circles.size(); k++){
circles.get(k).draw(g);
}
} // draw the circle
}