【问题标题】:JPannel not having the size setted in the setSize methodJPanel 没有在 setSize 方法中确定大小
【发布时间】:2020-09-20 07:02:54
【问题描述】:

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

我用 setSize(600, 400); 创建了一个 JFrame;我添加了窗格。这是代码

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;
}

这是画布类


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) {}

}

它似乎在高度上不起作用。在画布类中,我有一个显示单击位置的鼠标单击事件。我单击的宽度和输出是左侧的坐标(0,?)和右侧的(400,?)。问题是高度,在顶部我得到 (?, 0) 但在底部我能得到的最高值是 (?, 370) 而不是 (?, 400)。我的问题是:为什么底部不去(?,400)? 感谢您的帮助,如果有不清楚的地方,请询问它

编辑: 该计划的其他类别是: 一个向量类:

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 接口:

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);

}

【问题讨论】:

  • 当您将 JDK 中的类名用于您自己的类时,会让人感到困惑。例如,您发布的代码中的类Vector 不是java.util.Vector,是吗?那么你的班级Vector的代码在哪里?
  • 您使用 setPreferredSize 方法请求 JPanel 的大小。
  • 不,它不是java.util.Vector,我认为没有必要发布Vector类,我会放代码。如果您需要更多课程,请告诉我
  • @GilbertLeBlanc 你能解释一下吗?
  • 所以首先让面板尺寸正确。一旦可行,您就开始添加您的绘画逻辑。编码大约是一次一步。写一段代码,测试一下。然后添加更多并测试。不要尝试使用所有额外代码来测试面板的基本尺寸。如果您仍然有问题,那么您有一个 minimal reproducible example 可以发布。

标签: java swing


【解决方案1】:

我在这里看到很多 cmets(全部有效),但您要问的问题是为什么画布在右侧显示类似于 ~ 370 而不是 400(如果我没看错的话) .

您的画布可能是x,y(400,400),但根据您的初始调用,父容器只有 400 像素宽。很有可能您的窗口边框和其他操作系统特定元素添加了相当多的像素(在 Windows Vista/7 上,我似乎记得这是大约 30 像素),所以很有可能就是问题所在。

作为旁注(在 Java/Processing 中编写了一些粒子模拟),我可以说您可能希望使用 -1.0f/1.0f 代表画布的浮点数来查看 OpenGL 定位风格,而不是尝试做所有事情整数。首先,当您想要表示像素之间的值时,您将有很多不连贯的“反弹”处理整数。其次,这使得将您的模拟调整为任意 x/y 宽度非常容易。

https://learnopengl.com/Getting-started/Coordinate-Systems

祝你好运,五六年前我停止用 Java 编写 GUI,所以我有点生疏了。空布局可能会有问题,我建议选择一个布局管理器并使用setPreferredSize(我最喜欢的是 GridBag)。

【讨论】:

  • 非常感谢!我来看看那个坐标系统
猜你喜欢
  • 2011-09-29
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 2012-06-21
  • 2014-07-24
  • 2013-10-20
  • 2016-09-26
  • 2012-12-28
相关资源
最近更新 更多