Java Canvas Drawing

2019-08-15 19:36发布

问题:

Edit 4: A new formatting for the question

BACKGROUND: I have a class, Window, that extends JFrame, In the JFrame I have a canvas. To the canvas I add custom objects. The only purpose of this object(for argumenst sake) is to print a circle with text to the canvas. You can add multiple of these custom components to the canvas. When you add a new custom component it is placed 20 pixels(for now) away from the previous component added to the canvas.

PROBLEM: The canvas places the second circle at a position lets call it A, A is approximately in the centre of the form, The third circle added is placed at a position B, B is all the way to the right of the canvas, when more circles are added both positions A and B shift left. Irrespective of what I specify as the x and y coordinates of the drawOval function in the paint method this happens.

QUESTION: Is there a setting/function/option related to objects that you draw to eg Canvas and JFrame that will put the objects drawn to it at preset positions instead of where it is specified to draw

#

Everything posted before edit4:

Does a canvas in java have some sort of setting that I can disable which makes it place items where it wants.

public void paint(Graphics g){
  System.out.println("paint   X: "+x+"  Y: "+y);
  g.drawOval(x, y, RAD , RAD);
  System.out.println("paint 2nd   X: "+x+"  Y: "+y);

}

The following code does not place two circles at the same position when x and y are hard coded the .out's prove that x,y do not change so I am at a loss.( when two different objects call their draw function every one after the first one is placed at predefined positions but not where I specify it)

Edit: I have made a jar file that you can check to see what I mean, if you add a new node it should only be 60pixels away from the previous, and at a constant position. It can be found here

Edit2: I don't really know what code you could need, I do have a lot of code. Like explained before I have a JFrame, On the Jframe there is a canvas, to clarify more, I have objects which extend component each of which use the above code snippet as paint(which to my understanding gets called when repaint is called on the canvas) if you look at the example you can click the add node button, the first object (node) gets put at 0,0 which is correct, the second node you add should be placed 60 pixels to the right of the previous node added, but the second one you add always gets placed at around the centre of the canvas, no matter what the coordinates of that second item even if I hard code them. If you right click you can also add a new node and that node should be placed where you right clicked but also gets added to a random position on the canvas I have checked and double check the coordinates the function recieve so nothing at all is wrong with my coordinates, thats why the starting line of my question asks how to get the Items to be plaed where I am drawing them and not where the canvas wanst to place them.

Edit3: Aperantly my question is still unclear If you can look a the jar, and you have java installed you can run the jar with the folowing command assuming the jar is in your current directory in command prompt C:\Program Files\Java\jre1.6.0_04\bin\java.exe -jar Projek.jar, and for linux just java -jar Projek.jar . Ok for more code snippets.

In the Window class

public class Window extends JFrame implements   ActionListener{
...
Canvas panel;
...
private int globalX;
private int globalY;
...
public Window(){
...
graph=new Graph();

    panel = new Canvas();
panel.setLayout(new GridLayout(1, 2));
...
container.add(panel);
    container.add(btn_newNode,BorderLayout.SOUTH);
     addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }
      });

    setSize(1024,758);
    this.setVisible(true);
}
//Add Node gets called when you click on the button
public void addNode(String name){

    int ix;
    int iy;
    String itext=name;

    if(name.compareTo(".print") != 0){
    if(graph.VertexCount() > 0){
    Vertex temp=graph.getVertex(graph.VertexCount());

    if((temp.x + 20) < panel.getWidth() ){
        ix=temp.x + 20;
        iy=temp.y;
    }
    else{
        ix=temp.x;
        iy=temp.y + 20;
    }
    } else {
        ix=0;
        iy=0;
    }
        Vertex a=new Vertex(itext,ix,iy);
        graph.addVertex(a);
        panel.add(a);
        panel.revalidate();
      } else System.out.println(graph.toString());
    }


  public class Vertex<T> extends Component {
  private T data;
  public int x;
  public int y;
public final int RAD=50;
public Vertex( T data,int _x,int _y) {
incomingEdges = new ArrayList<Edge<T>>();
outgoingEdges = new ArrayList<Edge<T>>();
visited = false;
this.data = data;
x=_x;
y=_y;
System.out.println("X: "+x+"  Y: "+y);

}
public void paint(Graphics g){
  System.out.println("paint   X: "+x+"  Y: "+y);
  g.drawString(data.toString(), x+4, y+27);
  g.drawOval(x, y, RAD , RAD);

  //g.drawOval(20, 0, RAD , RAD);
  System.out.println("paint 2nd   X: "+x+"  Y: "+y);
}

That is everything that I can think is relavant, But I have been wrong before ^

回答1:

Your Vertex components are being added to a container (the Canvas) with a GridLayout. GridLayout is trying to position/bound the Vertex components. The coordinate system in the paint method of the Vertex is relative to the position/bounds of the component. You're mixing two coordinate systems and object hierarchies. Unless you REALLY need the Vertex to be a component, I could reorganize your object structure. If you DO need Vertex to be a component then you'll want to use NO layout manger (or a custom manager) and use the Component coordinates for the Vertex objects for rendering. The solution is very different depending on your requirements.



回答2:

The method signature for drawOval is:

public abstract void drawOval(int x,
                              int y,
                              int width,
                              int height)

The result is a circle or ellipse that fits within the rectangle specified by the x, y, width, and height arguments.

The x and y position are relative to the canvas, and are not the center of the oval. They represent a position to the upper left of the oval.

The width and height, when they are the same, are the diameter of the circle, not the radius.

Edited to respond to changes in the question.

Some of us cannot access web file storage. We are at work, and our firewalls do not allow us access. Even if we could access it, it's a lot of trouble to download a jar, unpack the jar, and open up an IDE to see what you're doing. If you want our help, you need to put some effort in asking the question.

Calling the drawOval method draws an oval based on the parameters passed. If the oval is not in the correct place on the canvas, then the parameters are wrong.

Finally, for the benefit of others coming across this answer in the future. If you want to draw a circle, and you have a center point x, y, and a radius RAD, then the following method call will draw the circle you're expecting.

g.drawOval(x - RAD, y - RAD, RAD + RAD, RAD + RAD);