JPanel的位置和大小变化很奇怪



我即将编写一个小版本的"Pong"。但是我的JPanels已经有问题了。Shields的大小从100变为10,这非常奇怪。没有任何方法可以改变它的大小!同时,护盾跳到JPanel的中上部。他们不会那样做。在帖子末尾的两张截图上可以看到。(Puu.sh)

很抱歉,我只是错过了一些显而易见的东西,但正如我所说,我正在训练。

带有psvm()的Main

public class Main {
public static void main(String[] args) {
    new Field();
}
}

场(包含游戏的帧)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
public class Field extends JFrame {
private Room room = new Room();
public Field() {
    this.setSize((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 1.5), (int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 1.5));
    this.setLayout(null);
    this.setLocation((int) ((Toolkit.getDefaultToolkit().getScreenSize().getWidth() - (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 1.5)) / 2), (int) ((Toolkit.getDefaultToolkit().getScreenSize().getHeight() - (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 1.5)) / 2));
    this.getContentPane().setBackground(Color.GRAY);
    this.setResizable(true);
    this.setEnabled(true);
    this.setMinimumSize(new Dimension(1000, 455));
    if (getHeight() < 455) {
        this.setSize(getWidth(), 455);
    } else if (getWidth() < 1000) {
        this.setSize(1000, getHeight());
    }
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    this.add(room);
    this.setVisible(true);
    addMouseListener(this);
    this.addComponentListener(new ComponentAdapter() {
        public void componentResized(ComponentEvent evt) {
            room.updateLocation(getSize());
        }
    });

}
}

房间

import javax.swing.*;
import java.awt.*;
public class Room extends JPanel {

private Shield shieldL = new Shield(0); // LEFT side
private Shield shieldR = new Shield(1); // RIGHT side
public Room() {
    this.setBackground(new Color(122, 197, 205));
    this.add(shieldL);
    this.add(shieldR);
}
public void updateLocation(Dimension d) {
    this.setSize((int) d.getWidth(), (int) (d.getHeight() - (d.getHeight() / 5)));
    this.setLocation(0, (int) (d.getHeight() / 10));
    shieldL.updateLocation(getSize());
    shieldR.updateLocation(getSize());
    this.setVisible(true);
}
}

屏蔽

import javax.swing.*;
import java.awt.*;
public class Shield extends JPanel {
private int side = 0;
public Shield(int s) { //0 = Left  |  1 = Right
    side = s;
    this.setSize(10, 100);
    this.setBackground(Color.white);
}
public void updateLocation(Dimension d) {   //Bug found here
    System.out.println(getSize());          //Bug seems not to be created here?
    int xPos;
    if (side == 0) {
        xPos = (int) (d.getWidth() / 8);
    } else {
        xPos = (int) (d.getWidth() / 8 * 7 - this.getWidth() / 2);
    }
    this.setLocation(xPos, (int) (d.getHeight() / 2 - (getHeight() / 2)));
    this.setVisible(true);
}
}

它们最终是这样的:在随机帧大小更改时切换位置。

http://puu.sh/ceyE0/ef15ee1748.png

http://puu.sh/ceyFN/122174db48.png

谢谢!Julian:)

Shield中,更改行

setSize(10, 100);

setPreferredSize(new Dimension(10, 100));

不要使用setSize方法,它们是在内部调用的。

编辑:

只尝试这两个类:

public class Field extends JFrame {
    private Room room = new Room();
    public Field() {
        //Mock panel
        JPanel filler = new JPanel();
        filler.setOpaque(false);
        getContentPane().setBackground(Color.GRAY);
        getContentPane().add(filler, BorderLayout.PAGE_START);
        getContentPane().add(room);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(1000, 455));
        setLocationRelativeTo(null);
        pack();
        room.init();
        setVisible(true);
    }
}

public class Room extends JPanel {
    private static int leftWidth = 100;
    private static int leftHeight = 100;
    private static int leftX;
    private static int leftY;
    private static int rightWidth = 100;
    private static int rightHeight = 100;
    private static int rightX;
    private static int rightY;
    public Room() {
        setBackground(new Color(122, 197, 205));
    }
    void init() {
        leftX = getWidth() / 8;
        leftY = getHeight() / 2 - leftHeight / 2;
        rightX = getWidth() * 7 / 8;
        rightY = getHeight() / 2 - rightHeight / 2;
    }
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.WHITE);
        g2d.fillRect(leftX, leftY, leftWidth, leftHeight);
        g2d.fillRect(rightX, rightY, rightWidth, rightHeight);
    }
}

您的问题是不了解布局管理器以及它们如何处理或使用setSize、setPreferredSize、setMinimumSize和setMaximumSize方法。

对于面板类,setSize不起作用,因为在创建JPanel时,它使用FlowLayout作为默认布局管理器,而布局管理器忽略由setSize方法指定的大小。您必须在某种组合中使用其他组合(至少一个)。使用setSize的唯一方法是用于默认情况下不分配布局管理器的组件,或者通过调用setLayout(null)。这就是所谓的绝对定位。这是您必须指定每个组件的位置和大小的地方。

搜索Java Swing教程并搜索"如何使用布局管理器"。如果你正在使用Swing,那么你理解这个概念是至关重要的,因为不同的布局管理器遵循不同的大小和定位规则。例如,Flow Layout和Grid Layout的行为非常不同。

当然,绝对定位是一种痛苦的方法,但它为您提供了对Swing组件大小和定位的绝对控制。但是,了解布局管理器并正确使用它们可以为创建GUI节省大量时间。

*****更新的信息*****调整框架大小的问题是由于您的面板正在使用FlowLayout。此布局管理器允许重新排列面板中的组件。有几种方法可以解决这个问题。一种是使用布局管理器,在调整组件大小时保留组件的纵横比。例如,GridLayout将组件"分解"为多个网格。如果你想到一个棋盘,它是一个8x8的网格。如果你把面板做成一个完美的正方形,那么所有的网格都将是大小相等的正方形。调整面板大小时,会保留面板的纵横比(不一定是内部组件)。另一种方法,也许是在学习如何正确使用布局管理器时最好的选择,是防止调整框架的大小。

相关内容

  • 没有找到相关文章

最新更新