我即将编写一个小版本的"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的网格。如果你把面板做成一个完美的正方形,那么所有的网格都将是大小相等的正方形。调整面板大小时,会保留面板的纵横比(不一定是内部组件)。另一种方法,也许是在学习如何正确使用布局管理器时最好的选择,是防止调整框架的大小。