I'm trying to draw a game map using many rectangular shapes(just like a screen contains many pixels). I'm using graphics 2D and fillRect(int x, int y, width, height) method. I make the rectangular so small with 10 widths and 10 height.
How can I detect if someone clicks a rectangle? I have read other questions but I am still confused by how the mouse listener detects my small rectangle?
Can someone give me any other solution instead of making pixels with a rectangular shape? maybe like buttons or something?
Here is my example code of making multiple rectangle :
public void paint (Graphics g){
Graphics2D g2D = (Graphics2D) g;
for (int j = 0; j<Map.WIDTH; j++){
if(j==100){
if(map[i][j]=='#'){
x=50;
y+=10;
g2D.setColor(Color.BLACK);
g2D.fillRect(x, y, 10, 10);
x+=10;
y+=0;
}
note: just ignore the iteration because i'm iterate from some input file(a template)
Is it a class that extends JPanel ?
Generally you have to set your listener on your JPanel or whatever:
void setListener(MouseListener listener) {
myPanel.addMouseListener(listener);
}
then in your listenerClass you do something like that :
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
class ControlButton extends MouseAdapter {
private MyViewClass view;
ControlButton(MyViewClass view) {
this.view = view;
view.setListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
//if my x and y point represent the upper left corner
int rectX = view.getMyRectX();
int rectY = view.getMyRectY();
int rectWidth = view.getRectWidth();
int rectHeight = view.getRectHeight();
if (e.getX() > rectX && e.getX() < rectX + rectWidth
&& e.getY() > rectY && e.getY() < rectY + rectHeight) {
System.out.println("YES");
}
}
}
Of course, I suppose you are working with Swing. If it is not what you want, please be more precise in your explanation ;)
Related
I am currently working on a 3 cushion billiards game project. I have added two balls on the table so far. I am trying to move one of the balls but I am having a hard time doing that. Should I use a timer? If so then could you tell me an effective way to use the timer on my code so I can move my balls?
Your help would be much appreciated.
Thanks in advance.
Farhan Hasan
I have tried to create a move function for the class balls. But I am not sure what I should put inside the function, I have added the xSpeed and ySpeed. The xLocation and the yLocation changes depending on the xSpeed and ySpeed.
public class Balls
{
private Color ballFillColor;
private Color ballBorderColor;
private int ballX = 0;
private int ballY = 0;
private int xSpeed = 5;
private int ySpeed = 0;
private int ballWidth = 0;
private int ballHeight = 0;
Timer t;
public boolean fillBall = false;
private static Balls ballArray[]; //Required for drawMultipleBalls
Balls(){ //Constructor
ballBorderColor = Color.black;
}
Balls(int ballX, int ballY, int ballWidth, int ballHeight, Color ballBorderColor, JFrame window){ //Constructor
// X , Y , Width, Height, Border Colour, container
this.setBallBorderColor(ballBorderColor);
this.setBallWidth(ballWidth);
this.setBallHeight(ballHeight);
this.setBallX(ballX);
this.setBallY(ballY);
this.drawBall(window);
}
//Here is the move function. I am not really sure what to do here.
public void move()
{
if(this.ballX < 1000 - this.ballWidth)
{
this.ballX += this.xSpeed;
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
//GET AND SET FUNCTIONS HERE
//HERE ARE THE FUNCTIONS WHICH ARE RESPONSIBLE FOR DRAWING MY BALLS IN JFRAME
public void drawBall(JFrame frame)
{
frame.getContentPane().add(new MyComponent());
}
public void drawMultipleBalls(JFrame frame, Balls[] balls)
{
ballArray = balls;
frame.getContentPane().add(new MyComponent2());
}
private class MyComponent extends JComponent{
public void paintComponent(Graphics g){
if (fillBall) //Fill first, and then draw outline.
{
g.setColor(ballFillColor);
g.fillOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
g.setColor(getBallBorderColor());
g.drawOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
}
private class MyComponent2 extends JComponent{
public void paintComponent(Graphics g){
for (int i = 0; i < ballArray.length; i++)
{
if (ballArray[i].fillBall) //Fill first, and then draw outline.
{
g.setColor(ballArray[i].ballFillColor);
g.fillOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
g.setColor(ballArray[i].getBallBorderColor());
g.drawOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
}
}
Hopefully, I can have two movable balls for the game, the should bounce back as the hit the edge of the screen and they should be able to slow down over time. For that, I am thinking to use a damper (I will multiply the xSpeed and ySpeed with a number less than 1, eventually it will slow down the ball)
Here is a simple example I came up with to show a ball moving and bouncing off the edges.
The direction changes based on the boundary. Left and top edges just check for 0. Bottom and right edges need to include the diameter of the ball.
The x and y increments are independent. And these amounts in conjunction with the timer can change the movement. Notice however, that to have objects bounce off of each other (as in a pool game) is more complicated due to angle of trajectories, etc. And the distances bounced will vary and slow with time based on frictional values. Everything else is documented in the Java API.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MovementDemo extends JPanel implements ActionListener {
JFrame frame = new JFrame("Movement Demo");
int size = 500;
int x = 50;
int y = 200;
int diameter = 50;
int yinc = 2;
int xinc = 2;
int xdirection = 1;
int ydirection = 1;
public MovementDemo() {
setPreferredSize(new Dimension(size, size));
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new MovementDemo().start());
}
public void start() {
Timer timer = new Timer(100, this);
timer.setDelay(5);
timer.start();
}
public void actionPerformed(ActionEvent ae) {
if (x < 0) {
xdirection = 1;
}
else if (x > size - diameter) {
xdirection = -1;
}
if (y < 0) {
ydirection = 1;
}
else if (y > size - diameter) {
ydirection = -1;
}
x = x + xdirection * xinc;
y = y + ydirection * yinc;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, diameter, diameter);
}
}
It seems in general there are a few things you need to figure out:
has the ball collided with another ball
has the ball collided with a wall
otherwise just figure out what is the ball's new position based on its velocity
Below is some sample code that stubs some of this out. You can first compare the current ball's position to all others (not including the current ball of course). If there are any equal positions, process a collision with a ball. If the ball is at the window border i.e it hit a wall, process a collision with a wall. Otherwise just calculate its new position based on its current velocity.
The process collision part is just to apply physics mechanics to whatever degree of complexity you require. One general suggested change would be to update the velocity of the balls then apply it to the position after. The specific calculations for velocity changes you could apply as needed and as you can imagine it can get pretty involved which is why I suggest using a separate method and possibly a sub class for velocity instead of managing each part of the velocity vector in the ball itself. I used the wall as an object because of this. The composition, weights, velocities etc of the object's colliding can affect the resulting collision, but how complex you want that processing to be is up to you.
Sorry I'm no physics expert but I hope this sends you in the right direction in terms of code! Also this might help with the specific calculations you might want to use:
https://www.khanacademy.org/science/physics/one-dimensional-motion/displacement-velocity-time/v/calculating-average-velocity-or-speed
public void move()
{
// check if balls are on same position not including this ball
for(Ball b: ballArray){
if (this.position == b.position && this != b){
processCollision(this, b, null);
} else{
// if the ball hasn't collided with anything process its movement based on speed
// this assumes a 1000 x 1000 window for keeping objects inside it
if(this.ballX < 1000 - this.ballWidth && this.ballY < 1000 - this.ballHeight){
this.ballX += this.xSpeed;
this.ballY += this.ySpeed;
}else {
processCollision(this, null, new Wall());
}
}
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
public void processCollision(Ball b1, Ball b2, Wall w){
// if ball hasn't collided with a wall, process a ball - ball collision
if(w == null){
// apply physics mechanics according the complexity desired for ball collisions
b1.xSpeed -= b2.xSpeed;
b1.ySpeed -= b2.ySpeed;
// ball 2 would end up slowing down
b2.xSpeed -= b1.xSpeed;
b2.ySpeed -= b1.ySpeed;
}
// if ball hasn't collided with a ball, process a ball - wall collision
if(b2 == null){
// apply physics mechanics for hitting a wall
// e.g as below: just send ball in opposite direction
b1.xSpeed = b1.xSpeed * -1;
b1.ySpeed = b1.ySpeed * -1;
}
// either way, process ball's new position based on its new speed
b1.ballX += b1.xSpeed;
b1.ballY += b1.ySpeed;
b2.ballX += b2.xSpeed;
b2.ballY += b2.ySpeed;
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am making a star using a draw line. I want to run a for loop to expand a star into multiple stars in a grid-like pattern. I am fairly new to java and could use some help with my code. The gride pattern that I would like the stars to open up too isn't too specific as far as columns x rows go. even making 6 stars or 9 stars is fine, as long as they are in a grid-like pattern.
So far, I have the star drawn with drawLine. At one point I got two stars but they were to close to each other. When I run the code it looks like I have a whole bunch of stars sort of staggered on top of each other and being able to get two stars on Star Field, I would like to get more in such 5x6 pattern or something close. I believe I might be having a hard time computing the math in the for loops to get this to happen.
Should I run, multiple nested for loops or is there a way to do this with using a minimal amount of for loops?
public static void drawFlag(int stars, int stripes, java.awt.Graphics
g, int x, int y, int width, int height) {
// Sets backround rectangle color to white
g.setColor(Color.WHITE);
g.fillRect(x, y, width, height);
// Draw filled red rectangles *stripes*
int stripeHeight = height/stripes;
g.setColor(Color.RED);
int lastStripeDrawnY = 0;
// For loop runs red stripes
for (int i = y; i < y + height - 2*stripeHeight; i = i + 2*stripeHeight)
{
g.fillRect(x, i, width, stripeHeight);
lastStripeDrawnY = i;
}
// expands strips across the rectangle
int lastStripeY = lastStripeDrawnY+2*stripeHeight;
int lastStripeHeight = y + height - lastStripeY;
if (stripes%2 != 0) {
g.fillRect(x, lastStripeY, width, lastStripeHeight);
}
int stars1 = 15;
for (int cols = 1; cols <= stars1; cols++) {
int rows = stars1/cols;
if (cols > rows && cols <2*rows && cols*rows == stars1) {
}
}
// Draws the starField
int numberOfRedStripes = (int)Math.ceil(stripes/2.0);
int starFieldHeight = numberOfRedStripes*stripeHeight;
int starFieldWidth = starFieldHeight*width/height;
g.setColor(Color.BLUE);
g.fillRect(x, y, starFieldWidth, starFieldHeight);
for (int x1 = 0; x1+100 <+ starFieldWidth-5; x1++) {
if(x1/5*4 == stars) {
drawStar(g,x1,y,50);
for(int y1 = 0; y1 <=starFieldHeight-5;y1++) {
if(y1/4*2 == stars) {
drawStar(g,x,y1,50);
}
}
}
}
}
// drawLine the star
public static void drawStar(java.awt.Graphics g, int x, int y, int size)
{
g.setColor(Color.WHITE);
g.drawLine(x+size/2, y+size/6, x+4*size/5, y+5*size/6);
g.drawLine(x+4*size/5,y+5*size/6, x+size/6, y+2*size/5);
g.drawLine(x+size/6, y+2*size/5, x+5*size/6, y+2*size/5);
g.drawLine(x+5*size/6, y+2*size/5, x+size/5, y+5*size/6);
g.drawLine(x+size/5, y+5*size/6, x+size/2, y+size/6);
}
}
Expand one star into a checkered grid-like pattern.
There are a number of ways you can approach this problem, you can, as you've started, simply try and build each star individually based on the required x/y position.
You could make a single star that was always at 0x0 and translate the Graphics context to the desire x/y position
Or, you could take advantage of the Shape API.
This allows you to define a self contained object which describes the shape you are trying to create.
public class StarShape extends Path2D.Double {
public StarShape(double size) {
double mid = size / 2d;
moveTo(mid, 0);
lineTo((size * 0.6d), (size * 0.4d));
lineTo(size, (size * 0.4d));
lineTo((size * 0.72d), (size * 0.58d));
lineTo((size * 0.85d), size);
lineTo((size * 0.5d), (size * 0.72d));
lineTo((size * 0.2), size);
lineTo((size * 0.325d), (size * 0.58d));
lineTo(0, (size * 0.4d));
lineTo((size * 0.4d), (size * 0.4d));
closePath();
}
}
There are lots of side benefits to this, but the immediate benefit is that it's "paintable". You can pass an instance of it directly to Graphics2D and have it painted and/or filled based on your needs.
Now, with that in hand, you can do something like...
public class TestPane extends JPanel {
private StarShape star;
private double starSize = 10;;
public TestPane() {
star = new StarShape(starSize);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
double y = 0;
for (int yIndex = 0; yIndex < getHeight() / starSize; yIndex++) {
double x = 0;
for (int xIndex = 0; xIndex < getWidth() / starSize; xIndex++) {
AffineTransform at = AffineTransform.getTranslateInstance(x, y);
PathIterator path = star.getPathIterator(at);
GeneralPath p = new GeneralPath();
p.append(path, true);
g2d.fill(p);
x += starSize;
}
y += starSize;
}
g2d.dispose();
}
}
The reason I'd prefer this method, is it doesn't affect the origin of the original starShape. You could also use the technique to cache the results, so you're not repeatedly doing it in the paintComponent method.
You could also do something like...
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
double y = 0;
for (int yIndex = 0; yIndex < getHeight() / starSize; yIndex++) {
double x = 0;
for (int xIndex = 0; xIndex < getWidth() / starSize; xIndex++) {
Graphics2D starg = (Graphics2D) g2d.create();
starg.translate(x, y);
starg.fill(star);
starg.dispose();
x += starSize;
}
y += starSize;
}
g2d.dispose();
}
Which changes the origin of the Graphics context instead or something like...
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
double xCount = getWidth() / starSize;
for (int yIndex = 0; yIndex < getHeight() / starSize; yIndex++) {
for (int xIndex = 0; xIndex < getWidth() / starSize; xIndex++) {
g2d.fill(star);
star.transform(AffineTransform.getTranslateInstance(starSize, 0));
}
star.transform(AffineTransform.getTranslateInstance(-(starSize) * xCount, starSize));
}
g2d.dispose();
}
which changes the origin of the star itself.
Personally, I prefer not to affect the original and instead simply change the context in how it's painted, but which method you use will come down to your needs.
Okay, that might seem like a lot of work for little gain, but the Shapes API is extremely powerful. Because it's point based (instead of pixel based), it can be more easily resized, without generating pixilation. It's very simple to rotate, through the use of AffineTransform and makes for a much simpler point of re-use.
Want to make the stars bigger? Simply change starStar, for example...
private double starSize = 50;
and the API takes care of the rest...
I used your drawStar() function and built this StarPanel. Try it and see if it gives you some hints for what you are trying to achieve.
Note that I removed g.setColor(Color.WHITE); line from your drawStar() function. We need to be careful when we set color of Graphics object. In many cases, this is the reason why we don't see what we draw.
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
public class StarPanel extends JPanel
{
private int xStarting;
private int yStarting;
private int numberOfRows;
private int numberOfColumns;
private int xDisplacement;
private int yDisplacement;
public StarPanel(int xStarting, int yStarting,
int numberOfRows, int numberOfColumns,
int xDisplacement, int yDisplacement)
{
this.xStarting = xStarting;
this.yStarting = yStarting;
this.numberOfRows = numberOfRows;
this.numberOfColumns = numberOfColumns;
this.xDisplacement = xDisplacement;
this.yDisplacement = yDisplacement;
}
public static void main(String[] args)
{
StarPanel starPanel = new StarPanel(50, 50, 5, 6, 75, 75);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(starPanel);
frame.setBounds(300, 200, 500, 600);
frame.setVisible(true);
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
for (int row = 0; row < numberOfRows; row++) {
for (int column = 0; column < numberOfColumns; column++) {
drawStar(g, xStarting + (row * xDisplacement), yStarting + (column * yDisplacement), 50);
}
}
}
// drawLine the star
public static void drawStar(java.awt.Graphics g, int x, int y, int size)
{
g.drawLine(x+size/2, y+size/6, x+4*size/5, y+5*size/6);
g.drawLine(x+4*size/5,y+5*size/6, x+size/6, y+2*size/5);
g.drawLine(x+size/6, y+2*size/5, x+5*size/6, y+2*size/5);
g.drawLine(x+5*size/6, y+2*size/5, x+size/5, y+5*size/6);
g.drawLine(x+size/5, y+5*size/6, x+size/2, y+size/6);
}
}
I am trying to change the y position of the rectangle, however, whenever I try to, it expands/gets bigger vertically.
public class PlayerPaddle implements Paddle {
double yVelocity;
final double GRAVITY = 0.94;
//move up/down faster (if not accelerating = slow down)
boolean upAccel, downAccel;
//determines if player 1 or player 2 (on left or on right)
int player;
//position of actual paddle
int x;
double y;
Rectangle panel;
public PlayerPaddle(int player) {
upAccel = false;
downAccel = false;
y = 210; //not moving initially
yVelocity = 0;
if (player == 1) {
//left side
x = 20;
} else {
//right side
x = 660;
}
}
#Override
public void draw(Graphics g) {
//draw paddle
g.setColor(Color.WHITE);
g.fillRect(x, (int) y, 20, 80);
}
#Override
public void move() {
if (upAccel) {
yVelocity -= 2;
} else if (downAccel) {
yVelocity += 2;
} else if ((!upAccel) && (!downAccel)) {
yVelocity *= GRAVITY;
}
y += yVelocity; //changes y position of paddle
}
public void setUpAccel(boolean input) {
upAccel = input;
}
public void setDownAccel(boolean input) {
downAccel = input;
}
#Override
public int getY() {
return (int) y;
}
}
I want to know how to make the rectangle move up and down vertically. A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding. But even when I say g.clearRect(...) it still expands and does not move.
I am new to Swing and Awt but I am really committed to learning. Thanks for the help.
A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding
And that is still probably the problem here.
Somewhere, not in the code presented here, you need to invoke the draw(...) method of this class.
So in that code you need to make sure the background of the component is cleared before you draw the paddle. Since you should be overriding the paintComponent(...) method of a panel to do custom painting your code should look something like:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
// draw the paddle
}
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
I am new to Swing and Awt but I am really committed to learning.
Then keep a link to the tutorial handy for all Swing basics.
Just started messing around with Swing for a class project GUI in Java. I'm trying to draw a game board, however, not a conventional one. I'm trying to draw one more like a parchessi board, so each board tile needs to have a specific location rather than a grid.
So far, I've run into this issue. In paint(), I'm trying to paint 5 rectangles, odd ones blue and empty, even ones red and filled in. However, instead of a nice checkered pattern, I get this:
Can anyone help me figure out why it's doing this?
Code:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Rectangles extends JPanel {
public static void main(String[] a) {
JFrame f = new JFrame();
f.setSize(800, 800);
f.add(new Rectangles());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public void paint(Graphics g) {
int x = 15;
int y = 15;
int w = 15;
int h = 15;
for(int i = 0; i < 5; i++){
if(i%2==0){
g.setColor(Color.RED);
g.fillRect (x, y, x+w, y+h);
}
else{
g.setColor(Color.BLUE);
g.drawRect (x, y, x+w, y+h);
}
x+=15;
System.out.println(Integer.toString(x) + ' ' + Integer.toString(y) + '|' + Integer.toString(w) + ' ' + Integer.toString(h));
}
}
}
Output from the Println statement(x,y,width,height):
30 15|15 15
45 15|15 15
60 15|15 15
75 15|15 15
90 15|15 15
It looked like there was overlap in the first image, so I modified the code and tried this:
for(int i = 0; i < 5; i++){
g.setColor(Color.BLUE);
g.drawRect (x, y, x+w, y+h);
x+=15;
}
Here's what happens with this code:
Why is there overlap? What causes this?
Also, does anyone know a good way to make an easily modifiable array of Rectangles? Or any good advice or tools for drawing that type of board?
Welcome to the reasons you should not break the paint chain...
Start by calling super.paint(g) as the first line of your paint method, before you do any custom painting.
A better solution would be to override paintComponent instead of paint, but still making sure you call super.paintComponent before you perform any custom painting...
Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
Next, start reading the JavaDocs on Graphics#fillRect, you will see that the last two parameters represent the width and height, not the x/y position of the bottom corner
public class Rectangles extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = 15;
int y = 15;
int w = 15;
int h = 15;
for (int i = 0; i < 5; i++) {
if (i % 2 == 0) {
g.setColor(Color.RED);
g.fillRect(x, y, w, h);
} else {
g.setColor(Color.BLUE);
g.drawRect(x, y, w, h);
}
x += 15;
System.out.println(Integer.toString(x) + ' ' + Integer.toString(y) + '|' + Integer.toString(w) + ' ' + Integer.toString(h));
}
}
}
Hey Guys I have succesfully made a GUI in java that will scale polygons and circles using a slider. Everything works but I was wondering if there is a way to change the Origin point(Where it scales from). Right now it scales from the corner and I would like it to scale from the middle so I can start it in the middle and it scales out evenly. Also, If anyone could tell me an easy way to replace the Rectangle I have with an Image of some kind so you can scale the Picture up and down would be great! Thank you! Here is my code:
import javax.swing.*;
public class Fred
{
public static void main(String[] args)
{
TheWindow w = new TheWindow();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //X wont close the window with out this line
w.setSize(375,375);
w.setVisible(true);
}
}
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class TheWindow extends JFrame
{
private JSlider slider; //declare slider
private drawRect myPanel; //declare/ create panel
public TheWindow()
{
super("Slider Example"); //make title
myPanel = new drawRect();
myPanel.setBackground(Color.green); //change background color
slider = new JSlider(SwingConstants.VERTICAL, 0, 315, 10);// restrains the slider from scaling square to 0-300 pixels
slider.setMajorTickSpacing(20); //will set tick marks every 10 pixels
slider.setPaintTicks(true); //this actually paints the ticks on the screen
slider.addChangeListener
(
new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
myPanel.setD(slider.getValue()); //Wherever you set the slider, it will pass that value and that will paint on the screen
}
}
);
add(slider, BorderLayout.WEST); //similar to init method, adds slider and panel to GUI
add(myPanel, BorderLayout.CENTER);
}
}
import java.awt.*;
import javax.swing.*;
public class drawRect extends JPanel
{
private int d = 25; //this determines the beginning length of the rect.
public void paintComponent(Graphics g)//paints circle on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
g.fillRect(15,15, d, d); //paints rectangle on screen
//x , y, width, height
}
public void setD(int newD)
{
d = (newD >= 0 ? newD : 10); //if number is less than zero it will use 10 for diameter(compressed if statement)
repaint();
}
public Dimension getPrefferedSize()
{
return new Dimension(200, 200);
}
public Dimension getMinimumSize()
{
return getPrefferedSize();
}
}
Changing the "origin point" so it becomes the center of the "zoom" is basically just the process of subtract half of d from the center point.
So, assuming the the center point is 28 ((25 / 2) + 15), you would simply then subtract d / 2 (25 / 2) from this point, 28 - (25 / 2) = 15 or near enough...
I modified the paintComponent method for testing, so the rectangle is always at the center of the panel, but you can supply arbitrary values in place of the originX and originY
#Override
public void paintComponent(Graphics g)//paints circle on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
int originX = getWidth() / 2;
int originY = getHeight() / 2;
int x = originX - (d / 2);
int y = originY - (d / 2);
System.out.println(x + "x" + y);
g.fillRect(x, y, d, d); //paints rectangle on screen
//x , y, width, height
}
As for scaling an image, you should look at Graphics#drawImage(Image img, int x, int y, int width, int height, ImageObserver observer), beware though, this will scaling the image to the absolute size, it won't keep the image ratio.
A better solution might be to use a double value of between 0 and 1 and multiple the various elements by this value to get the absolute values you want