In my program I'm adding a JPannel that I'm using as canvas to a JFrame. The problem is that the size of the JPannel#setSize() is not what it is displayed. I first had a problem more or less like this one and I asked here Java questions about coordinates with Graphics They toldme to add the JPannel and use the pack() method and it worked but I can't get it to work now because the JFrame is larger than the JPannel where I am drawing. I have look at some threads to see if I coud fiand an answer but I wasn't succesfull. Here are the threads I looked:
- Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
- Why the JProgressBar doesn't respect the setSize()?
- Component setSize method in FlowLayout object
- setSize() not working?
- setSize not influencing size of button
- Why does the JFrame setSize() method not set the size correctly?
- java.AWT - setSize() method
- Java JPannel not Visible
I create a JFrame with setSize(600, 400); and I add the pane. Here is the code
import java.awt.Dimension;
import javax.swing.JFrame;
import me.nemo_64.particlessimulation.util.Canvas;
public class Frame extends JFrame {
private Frame(String title) {
super(title);
setResizable(false);
setSize(600, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setLayout(null);
init();
}
private void init() {
canvas = new Canvas();
canvas.setSize(400, 400);
canvas.setLocation(0, 0);
canvas.setPreferredSize(new Dimension(400, 400));
canvas.startDrawing();
add(canvas);
}
private Canvas canvas;
public static Frame getInstance() {
if (instance == null)
throw new IllegalAccessError("instanceFrame must be callen at least ones before this method");
return instance;
}
public static Frame instanceFrame(String title) {
if (instance != null)
return getInstance();
instance = new Frame(title);
return getInstance();
}
private static Frame instance;
private static final long serialVersionUID = 1L;
}
And here is the canvas class
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
public class Canvas extends ACanvas {
Vector p, dir;
float v;
public Canvas() {
p = new Vector(0, getHeight() / 2);
dir = new Vector(50f, 50f);
v = 50;
}
@Override
public void update(float delta) {
if (p.x <= 0 && dir.x < 0)
dir.x *= -1;
if (p.y <= 0 && dir.y < 0)
dir.y *= -1;
if (p.x + 100 >= getWidth() && dir.x > 0)
dir.x *= -1;
if (p.y + 100 >= getWidth() && dir.y > 0)
dir.y *= -1;
Vector a = dir.clone().multiply(delta);
p.add(a);
}
@Override
public void mouseClicked(MouseEvent e) {
System.out.println(e.getX() + " " + e.getY());
}
@Override
public void draw(Graphics2D g) {
System.out.println(g);
fill(255, 0, 0);
fillRectangle(p.x, p.y, 100, 100);
}
}
And here is the ACanvas class
package me.nemo_64.particlessimulation.util;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import javax.swing.JPanel;
import javax.swing.event.MouseInputListener;
public abstract class ACanvas extends JPanel
implements KeyListener, MouseInputListener, MouseWheelListener, Drawable, Updateable, FigureDrawer {
private Graphics2D g;
private Thread drawThread;
private Color backgroundColor;
private Color actualColor;
private long lastTime = 0;
private float delta = 0;
public ACanvas() {
setFocusable(true);
addKeyListener(this);
addMouseListener(this);
addMouseWheelListener(this);
lastTime = System.currentTimeMillis();
drawThread = new Thread(() -> {
while (true)
repaint();
}, "Drawing thread");
}
@Override
/**
* Used to update all the components to be drawn
*/
public abstract void update(float delta);
/**
* Draws all the comsponents
*/
public void draw(Graphics2D g) {}
@Override
public Graphics2D getGraphics2D() {
return this.g;
}
@Override
/**
* Draws all the comsponents
*/
public void draw(Graphics g) {
this.g = (Graphics2D) g;
draw(this.g);
}
@Override
public void paint(Graphics g) {
super.paint(g);
delta = (System.currentTimeMillis() - lastTime) * 0.001f;
lastTime = System.currentTimeMillis();
clearBackground(g);
update(delta);
g.setColor(actualColor);
draw(g);
}
public void clearBackground(Graphics g) {
g.setColor(backgroundColor);
g.fillRect(0, 0, getWidth(), getHeight());
}
public void startDrawing() {
if (!drawThread.isAlive())
drawThread.start();
}
public void stopDrawing() {
if (drawThread.isAlive())
drawThread.interrupt();
}
public void background(Color c) {
backgroundColor = c;
}
public void background(int c) {
backgroundColor = new Color(c);
}
public void background(int r, int g, int b) {
backgroundColor = new Color(r, g, b);
}
public void background(float r, float g, float b) {
backgroundColor = new Color(r, g, b);
}
public void fill(Color c) {
actualColor = c;
g.setColor(c);
}
public void fill(int c) {
fill(new Color(c));
}
public void fill(float r, float g, float b) {
fill(new Color(r, g, b));
}
public void fill(int r, int g, int b) {
fill(new Color(r, g, b));
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseDragged(MouseEvent e) {}
@Override
public void mouseMoved(MouseEvent e) {}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {}
@Override
public void keyPressed(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {}
@Override
public void keyTyped(KeyEvent e) {}
}
It doen't seem to work in the height. In the canvas class I have a mouse click event that displays the position of the click. The width I click and the output is a coordenade like (0, ?) for the left and (400, ?) for the right. The problem is the height, at the top I get (?, 0) but at the bottom the highest value I could get is (?, 370) and not (?, 400). My question is: why the bottom doesn't go to (?, 400)? Thanks for the help, if something is not clear just ask it
EDIT: Other clases of the program are: A vector class:
public class Vector {
public float x, y, z;
public Vector(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public Vector(float x, float y) {
this(x, y, 0);
}
public Vector() {
this(0f, 0f, 0f);
}
public Vector multiply(float... values) {
for (float f : values) {
x *= f;
y *= f;
z *= f;
}
return this;
}
public Vector divide(float... values) {
for (float f : values) {
x /= f;
y /= f;
z /= f;
}
return this;
}
public Vector add(Vector... vectors) {
for (Vector v : vectors)
add(v.x, v.y, v.z);
return this;
}
public Vector add(float x, float y, float z) {
this.x += x;
this.y += y;
this.z += z;
return this;
}
public Vector add(float x, float y) {
return add(x, y, 0);
}
public Vector remove(Vector... vectors) {
for (Vector v : vectors)
remove(v.x, v.y, v.z);
return this;
}
public Vector remove(float x, float y, float z) {
this.x -= x;
this.y -= y;
this.z -= z;
return this;
}
public Vector remove(float x, float y) {
return remove(x, y, 0);
}
public Vector normalize() {
double mod = module();
this.x /= mod;
this.y /= mod;
this.z /= mod;
return this;
}
public double module() {
return Math.sqrt(moduleSquared());
}
public double moduleSquared() {
return (double) (x * x + y * y + z * z);
}
public Vector clone() {
return new Vector(x, y, z);
}
@Override
public String toString() {
return "[ " + x + ", " + y + ", " + z + "]";
}
}
A drawing interface:
package me.nemo_64.particlessimulation.util;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
public interface FigureDrawer {
default public void fillRectangle(float x, float y, float width, float height) {
getGraphics2D().fill(new Rectangle2D.Float(x, y, width, height));
}
default public void drawRectangle(float x, float y, float width, float height) {
getGraphics2D().draw(new Rectangle2D.Float(x, y, width, height));
}
default public void fillCircle(float x, float y, float r) {
fillCircle(x, y, r, r);
}
default public void drawCircle(float x, float y, float r) {
drawCircle(x, y, r, r);
}
default public void fillCircle(float x, float y, float r1, float r2) {
getGraphics2D().fill(new Ellipse2D.Float(x, y, r1, r2));
}
default public void drawCircle(float x, float y, float r1, float r2) {
getGraphics2D().draw(new Ellipse2D.Float(x, y, r1, r2));
}
public Graphics2D getGraphics2D();
}
And the Drawable and Updateable interfaces:
package me.nemo_64.particlessimulation.util;
public interface Updateable {
/**
* Called when the component must be updated
* @param delta The seconds that past between calls
*/
public void update(float delta);
}
package me.nemo_64.particlessimulation.util;
import java.awt.Graphics;
public interface Drawable {
/**
* Called when the component must be drawn
*/
public void draw(Graphics g);
}