【发布时间】:2022-01-14 19:33:08
【问题描述】:
我正在尝试为我创建的满足以下特定条件的基于迷宫的游戏实现 GUI:
-
GUI 本身有一个固定的大小并且不可调整大小(第 41 行)。
-
包含所有迷宫图像的主面板(第 57 行)是可滚动的。所有迷宫图像组件彼此齐平。
- 如果迷宫足够小,则整个迷宫都将在主面板中可见。
- 如果迷宫很大,则用户需要滚动。
-
主面板需要通过鼠标侦听器(第 130 行)访问,该侦听器返回被点击的组件。
以下代码似乎符合标准 1 和 3,但不符合标准 2:
public class MazeGui extends JFrame implements DungeonView {
private final Board board;
public MazeGui(ReadOnlyModel m) {
//this.setSize(m.getNumRows()*100, m.getNumCols()*100);
this.setSize(600, 600);
this.setLocation(200, 200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.board = new Board(m);
JScrollPane scroller = new JScrollPane(board);
this.add(scroller, BorderLayout.CENTER);
setTitle("Dungeon Escape");
}
private class Board extends JPanel {
private ReadOnlyModel m;
public Board(ReadOnlyModel m) {
this.m = m;
GridLayout layout = new GridLayout(m.getNumRows(),m.getNumCols(), 0, 0);
// layout.setHgap(-100);
// layout.setVgap(-100);
this.setLayout(layout);
this.setSize(m.getNumRows()*64,m.getNumCols()*64);
for (int i = 0; i < m.getNumRows() * m.getNumCols(); i++) {
try {
// load resource from the classpath instead of a specific file location
InputStream imageStream = getClass().getResourceAsStream(String.format("/images/%s.png", m.getRoomDirections(i + 1)));
// convert the input stream into an image
Image image = ImageIO.read(imageStream);
// add the image to a label
JLabel label = new JLabel(new ImageIcon(image));
label.setPreferredSize(new Dimension(64, 64));
JPanel panel = new JPanel();
panel.setSize(64, 64);
String name = String.format("%d", i);
panel.setName(name);
panel.add(label);
// add the label to the JFrame
//this.layout.addLayoutComponent(TOOL_TIP_TEXT_KEY, label);
this.add(panel);
} catch (IOException e) {
JOptionPane.showMessageDialog(this, e.getMessage());
e.printStackTrace();
}
}
}
}
@Override
public void addClickListener(DungeonController listener) {
Board board = this.board;
MouseListener mouseListener = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println(String.format("(%d,%d)", e.getX(), e.getY()));
JPanel panel = (JPanel) board.getComponentAt(e.getPoint());
System.out.println(panel.getName());
}
};
board.addMouseListener(mouseListener);
}
@Override
public void refresh() {
this.repaint();
}
@Override
public void makeVisible() {
this.setVisible(true);
}
}
这是它产生的图像:
【问题讨论】:
-
1) 不要设置标签的首选尺寸。标签的大小将自动由图像的大小决定。如果您将首选尺寸设置为大于实际图像尺寸,您将获得额外空间。 2)不要将标签添加到子面板。面板的默认布局是 FlowLayout,它会增加额外的空间。只需使用 GridLayout 将标签直接添加到面板。
-
如需更好的帮助,请edit 添加minimal reproducible example。上面的代码需要至少导入才能成为 MRE。热链接到合适的图像,以便其他人可以轻松运行它。
-
@camickr 我实现了你的建议。除了现在我的 MouseListener 坏了,GUI 看起来一样。因此,标准 3 也不再满足。
-
1) 您永远不会将听众添加到董事会 2) 如果您需要更多帮助,则需要发布您的 minimal reproducible example。
-
@Nova 原来我应该使用 GridBagLayout!我 - 没有主要问题是您手动将框架的大小设置为(600x 600)。当您有一个由 8 个正方形组成的网格时,每个网格的大小为 64,您会使框架太大,以至于每个 JLabel 的大小都调整得太大。
Don't use setSize()。确定每个组件的大小是布局管理器的工作。相反,简单的解决方案是pack()框架在所有组件都添加到框架之后。那么就不会有差距了。