在我的程序中,我将用作 Canvas 的 JPannel 添加到 JFrame 中。问题是 JPannel#setSize() 的大小不是它显示的大小。 我第一次遇到或多或少像这样的问题,我在这里问 Java questions about coordinates with Graphics 他们告诉我添加 JPannel 并使用 pack() 方法,它有效,但我现在无法让它工作,因为 JFrame 比我正在绘制的 JPannel 大。 我查看了一些线程,看看我是否可以找到答案,但我没有成功。以下是我查看的主题:
- 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
我使用 setSize(600, 400) 创建一个 JFrame;我添加了 Pane 。这是代码
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;
}
这是 Canvas 类
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);
}
}
这是 ACanvas 类
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) {}
}
在高处似乎不起作用。在 Canvas 类中,我有一个鼠标单击事件,用于显示单击的位置。我单击的宽度和输出是一个坐标,例如左侧为 (0, ?) ,右侧为 (400, ?) 。问题是高度,在顶部我得到 (?, 0) 但在底部我能得到的最高值是 (?, 370) 而不是 (?, 400)。我的问题是:为什么底部没有到达(?,400)? 感谢您的帮助,如果有不清楚的地方请询问
编辑: 该计划的其他类(class)有: vector 类:
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 + "]";
}
}
绘图界面:
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();
}
以及 Drawable 和 Updateable 接口(interface):
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);
}
最佳答案
我在这里看到很多评论(全部有效),但您问的问题是为什么 Canvas 上显示类似〜370
而不是400
的内容右手边(如果我没读错的话)。
您的 Canvas 可能是x,y(400,400)
,但根据您的初始调用,父容器的宽度仅为 400px。您的窗口边框和其他操作系统特定元素很可能会添加相当多的像素(在 Windows Vista/7 上,我似乎记得这是 ~30px),所以很有可能这就是问题所在。
作为旁注(在 Java/Processing 中编写了一些粒子模拟)我可以说您可能想查看使用 -1.0f/1.0f 代表 Canvas 的 float 的 OpenGL 定位风格,而不是尝试做所有事情以整数表示。首先,当您想要表示像素之间的值时,您将在处理整数时遇到很多不稳定的“反弹”。其次,这使得将模拟大小调整为任意 x/y 宽度变得非常容易。
https://learnopengl.com/Getting-started/Coordinate-Systems
祝你好运,五六年前我就不再用 Java 编写 GUI,所以我有点生疏了。空布局可能会出现问题,我建议选择一个布局管理器并使用 setPreferredSize
(GridBag 是我的最爱)。
关于java - JPanel 没有在 setSize 方法中设置大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62141366/