JavaFX center a Ractangle within a Pane - java

I have the following code which makes a basic Pane with a Rectangle inside it:
public class Canvas extends Pane{
public Canvas() {
Rectangle rect = new Rectangle(50,50, Color.GOLD);
this.setBackground(new Background(new BackgroundFill(Color.INDIANRED,new CornerRadii(0),new Insets(0))));
this.setPrefSize(200, 200);
rect.setX((this.getMaxWidth()/2) + (rect.getWidth()));
rect.setY((this.getMaxHeight()/2) + (rect.getHeight()));
this.getChildren().add(rect);
}
I already tried a few things to get the center of the triangle at the center of the Pane (one example in the above code), but because in JavaFX the X and Y coordinates of a Rectangle represent the top left corner it has made it more difficult to center it within my pane. I am very bad at maths and dont know the correct formula to achieve this.
How can i get the center of my Rectangle to align with the center of my Pane?
Without using Stackpane etc...

You want to align the midpoint of the Rectangle with the midpoint of the Pane.
You have to find the midpoint of the pane (x and y), and the rectangle (x and y).
// Find the midpoint of the Pane.
// x midpoint
float xPaneMidpoint = pane.width / 2
// y midpoint
float yPaneMidpoint = pane.height/ 2
You then move the Rectangle to the position of the midpoint of the Pane, then offset it by half of its size
// Take the midpoint of the pane, and move the rectangle to that point.
// Then offset it by half its width/height
rectangle.setX( xPaneMidpoint - (rectangle.width / 2));
rectangle.setX( yPaneMidpoint - (rectangle.height/ 2));

Related

How to center a text in a rectangle in JavaFX

I am trying to draw a string exactly in the center of a rectangle using JavaFX GraphicsContext2D.
I don't want to use JavaFX components so please do not recommend them.
For example, I stroke a rectangle with attributes: x = 10, y = 10, width = 100, height = 100. Now I want to stroke a text in a way that it comes exactly in the center(horizontally and vertically) of the rectangle. How can I do it?
As #James_D comments, you can use the GraphicsContext methods setTextAlign() and setTextBaseline() to center the fillText() in an arbitrary Rectangle. Starting from this example, I added the following lines in the tooltips loop in order to produce the image shown:
gc.setTextAlign(TextAlignment.CENTER);
gc.setTextBaseline(VPos.CENTER);
gc.setFill(Color.BLACK);
gc.fillText(color.toString(),
bounds.getX() + bounds.getWidth() / 2,
bounds.getY() + bounds.getHeight() / 2);

How to zoom into mouse position with correct translation

I'm trying to zoom a grid in Processing and I am having trouble with applying the correct translation such that zooming is centered around the mouse position. I have searched the web for a while but nothing I try seems to work.
The screen size is width and height and the mouse position is mouseX and mouseY.
The code I have at the moment is below, but it zooms the grid (controlled by player.zoom) from the top left corner which is not what I want. To update the translation of the grid, player has the 2d vector player.translate.
void mouseWheel(MouseEvent event) {
float zoomFactor = 200.0f;
float scroll = event.getCount();
player.zoom -= scroll * player.zoom / zoomFactor;
// player.translate.x += something;
// player.translate.y += something;
}
If you need more details to answer I can link the repo with the source code.
I have created a very simple mock-up for you which will hopefully point you in the right direction into applying this to your player.
So this little demo shows the zooming in to the centre of an ellipse whilst keeping it as the central focus.
float scale = 1;
// displacement left/right
float xPan = 720;
// displacement up/down
float yPan = 450;
boolean zoomIn = true;
void setup() {
size(1440, 900);
}
void draw() {
// allows us to zoom into the center of the screen rather than the corner
translate(width/2, height/2);
scale(scale);
translate(-xPan, -yPan);
background(200);
// draws the ellipse in the center
ellipse(width/2, height/2, 100, 100);
// does the zooming
if (zoomIn) {
scale *= 1.01;
}
}
I suggest you to copy this into a new project and then comment out specific lines to try to understand what's going on and how you can transfer this over to your own project.
The same principles still apply, I didn't do this with mouse input in the effort of making the program as simple as possible.

Java graphics fill doesn't paint over graphics draw?

If you run the code below, you will see that there is a red square with a blue line along the bottom and right edges of the square. However, as you can see in the code, the parameters for the rectangle being drawn are the same as the rectangle being filled.
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.blue);
g.drawRect(50, 50, 100, 100);
g.setColor(Color.red);
g.fillRect(50, 50, 100, 100);
}
};
panel.setPreferredSize(new Dimension(200, 200));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
Does anyone know the reasoning behind this behavior? Or is this a bug in Java's codebase?
It seems like drawing the rectangle adds 1 to the width and height of the rectangle you specify. This seems like un-intuitive behavior for one, but in my case it is also causing some undesired effects for a gui I am building.
This behavior is also found when drawing polygons with horizontal/vertical lines. Is there a simple way of getting some consistency in what is painted between the graphics draw and fill functions? It would be great if there was a way for any arbitrary polygon to completely paint over a previously drawn polyline using the same points.
One approach I had thought of was to both draw and fill whenever I want to fill a polygon and then just draw when I want to draw the polygon.
This would actually work in cases of opaque polygons, but in my case I have both opaque and transparent polygons so this approach is not an option.
This is clearly documented in the Graphics API:
drawRect
public void drawRect(int x,
int y,
int width,
int height)
Draws the outline of the specified rectangle. The left and right edges of the rectangle are at x and x + width. The top and bottom edges are at y and y + height. The rectangle is drawn using the graphics context's current color.
and
fillRect
public abstract void fillRect(int x,
int y,
int width,
int height)
Fills the specified rectangle. The left and right edges of the rectangle are at x and x + width - 1. The top and bottom edges are at y and y + height - 1. The resulting rectangle covers an area width pixels wide by height pixels tall. The rectangle is filled using the graphics context's current color.
Note the difference in the calculation for the right and bottom edges. Although this difference is clearly documented, there is no justification for this difference.
Finally, note that the first line of paintComponent() should be super.paintComponent(g);. This will ensure that the super class has a chance to initialize things, including clearing the region where you will draw.

Flipping graphics object without using G2D?

Say I have a shape that I have drawn through paintComponent(), fillRect, or drawOval,
How would I go about flipping it, so that the shape would not be going from the top left, but from the bottom upwards?
All I had to do was use the height of my panel, and subtract it from the height of the object.
for ex:
int height = (1000 - n);
where n is the height that you wish the shape to be.

JSlider-Advice needed [duplicate]

I have a problem with JSlider in Java I have drawn a circle A, and I want to put ANOTHER circle B inside the first circle A. I want to place the CENTRE of the second circle B at the same coordinate with the centre of the first circle A, and then I want to use JSlider to INCREASE or DECREASE the radius of circle B. The trouble is, when you increase or decrease the slider, the CENTRE of circle B does not stay aligned with the centre of A. Basically, I want two circles with the SAME centre. Can someone point out my mistake, please?
slider1 = new JSlider(JSlider.HORIZONTAL,10,100,10);
window.add(slider1);
slider1.addChangeListener(this);
Graphics paper = panel.getGraphics();
int slider1Value = slider1.getValue();
paper.setColor(Color.white);
paper.fillRect(0, 0, 500, 500);
paper.setColor(Color.pink);
paper.fillOval(20,20,100,100); // this is circle A
paper.drawOval(60,60,slider1Value,slider1Value); // this is circle B slider
Because you have to change position of top-left "corner" of circle. If you change radius, the circle is bigger/smaller so it's obvious if you don't change position of top-left cornet, centers of 2 circles won't be aligned
Theory
From Graphics.drawOval() javadoc. When you draw a circle their (x,y) coordinates are not its center but its top-left corner. In order to make your B circle aligned with A circle, you need to calculate its (x,y) coordinates relatives to the last one:
Circle A: (x,y) = (20,20); diameter = 100 ==> radius = 50; center = (x + radius, y + radius) = (70,70)
Well, you have your center now: (70,70). Now, slider1Value is your new radius so you need to calculate circle B (x,y) coordinates:
Circle B: center = (70,70); (x,y) = (centerX - radius, centerY - radius) = (70 - slider1Value, 70 - slider1Value)
Finally, circle B width and height are equals to its diameter:radius * 2 = slider1Value * 2.
Facts
Make this change and it will work like a charm:
paper.drawOval(70 - slider1Value, 70 - slider1Value, 2*slider1Value, 2*slider1Value);

Categories