java - JPanel 没有在 setSize 方法中设置大小

标签 java swing

在我的程序中,我将用作 Canvas 的 JPannel 添加到 JFrame 中。问题是 JPannel#setSize() 的大小不是它显示的大小。 我第一次遇到或多或少像这样的问题,我在这里问 Java questions about coordinates with Graphics 他们告诉我添加 JPannel 并使用 pack() 方法,它有效,但我现在无法让它工作,因为 JFrame 比我正在绘制的 JPannel 大。 我查看了一些线程,看看我是否可以找到答案,但我没有成功。以下是我查看的主题:

我使用 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/

相关文章:

java - JScrollPane,添加到JPanel 还是JTable?

java - 粒子模拟器Java

java - JTable 表头和间隔行

java - 使用 Spring 3 MVC 的问题

java - 从rest api获取列表

java - Swing - windowStateChanged 事件问题

java - JSlider 从外部对象移动

java - Opencv java - 将图像加载到 GUI

java - struts2 : Problem in submitting same form to different actions

java - 如何使用 Java 在控制台中打印任何 PostgreSQL 查询结果?