【发布时间】:2013-02-09 03:53:40
【问题描述】:
我最近开始使用 java GUI - 最合适的是 Swing。
现在我遇到了这个问题,我无法解决。
我想处理一个扩展JPanel 并实现ActionListener(某些东西)的游戏板,如下所示:
+----------------+
| Panel1 | Board |
|________| |
| Panel2 | |
| | |
+----------------+
但我明白了:
+----------------+
| Panel1 | Board |
|________|_______|
| Panel2 | EMPTY |
| | |
+----------------+
我首先尝试将GridLayout 用于主窗格,其中包含BoxLayouted 面板,但这不起作用。然后我找到了GroupLayout,它把我带到了上面的案例中,让我在棋盘类中失去了听众的控制/注意力。
[编辑] 我还尝试更改了板的最小和首选尺寸,也没有奏效。
谁能告诉我为什么会这样?
正在恢复:
- 为什么组布局对董事会面板执行此操作?无论如何我可以解决它?
- 因为在 Board 类里面我做了 setFocusable(true);为什么进入组布局后它不能获取动作/事件?(没有它也能正常工作)
代码如下:
游戏类
...
public ConstructorOfTheClassThatExtendsJFrame() {
statusbar = new JLabel(" 0");
panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.black));
this.getContentPane().add(panel);
Board board = new Board(this);
GroupLayout layout = new GroupLayout(panel);
panel.setLayout(layout);
//Specify automatic gap insertion:
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
//PANEL 1
col1 = new JPanel();
col1.setBorder(BorderFactory.createLineBorder(Color.black));
//PANEL 3
col3 = new JPanel();
col3.add(statusbar);
layout.setHorizontalGroup(
layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(col1)
.addComponent(col3))
.addComponent(board)
);
layout.setVerticalGroup(
layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(col1)
.addComponent(board))
.addComponent(col3)
);
setSize(400, 400);
setResizable(false);
setTitle("GameOn");
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
还有我的董事会课程(来自ZetCode)
public Board(Game parent) {
setFocusable(true);
curPiece = new Shape();
timer = new Timer(400, this);
timer.start();
statusbar = parent.getStatusBar();
board = new Tetrominoes[BoardWidth * BoardHeight];
addKeyListener(new TAdapter());
clearBoard();
}
...
class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
if (!isStarted || curPiece.getShape() == Tetrominoes.NoShape) {
return;
}
int keycode = e.getKeyCode();
if (keycode == 'p' || keycode == 'P') {
pause();
return;
}
if (isPaused)
return;
switch (keycode) {
case KeyEvent.VK_LEFT:
tryMove(curPiece, curX - 1, curY);
break;
case KeyEvent.VK_RIGHT:
tryMove(curPiece, curX + 1, curY);
break;
case KeyEvent.VK_DOWN:
//tryMove(curPiece, curX, curY - 1);
oneLineDown();
break;
case KeyEvent.VK_UP:
tryMove(curPiece.rotateRight(), curX, curY);
break;
case KeyEvent.VK_SPACE:
dropDown();
break;
case 'd':
oneLineDown();
break;
case 'D':
oneLineDown();
break;
case KeyEvent.VK_SHIFT:
newPiece();
break;
}
}
[编辑] 经过一些建议,这里是一个 sscce 版本的代码,其中关键事件起作用但对齐仍然错误:
游戏类(本例是 hello world 但仍然)
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Color;
public class HelloWorldSwing{
private static void createAndShowGUI(){
//Create frame
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.black));
frame.getContentPane().add(panel);
//Create the new group layout
GroupLayout layout = new GroupLayout(panel);
panel.setLayout(layout);
//We specify automatic gap insertion:
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
//PANEL 1
JPanel col1 = new JPanel();
col1.setBorder(BorderFactory.createLineBorder(Color.black));
//PANEL 2
JLabel label2 = new JLabel("Col2");
Board board = new Board(label2, new BorderLayout());
//PANEL 3
JPanel col3 = new JPanel();
JLabel label = new JLabel("Col1");
JLabel label3 = new JLabel("Col3");
col1.add(label);
board.add(label2,BorderLayout.PAGE_END);
col3.add(label3);
layout.setHorizontalGroup(
layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(col1)
.addComponent(col3))
.addComponent(board)
);
layout.setVerticalGroup(
layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(col1)
.addComponent(board))
.addComponent(col3)
);
frame.setSize(300, 400);
frame.setVisible(true);
}
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
还有棋盘类:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.BorderLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class Board extends JPanel implements ActionListener {
JLabel blabel;
public Board(JLabel label, BorderLayout b) {
super(b);
setFocusable(true);
blabel = label;
addKeyListener(new TAdapter());
}
public void actionPerformed(ActionEvent e) {
}
class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
switch (keycode) {
case KeyEvent.VK_LEFT:
blabel.setText("Left");
break;
case KeyEvent.VK_RIGHT:
blabel.setText("Right");
break;
case KeyEvent.VK_DOWN:
blabel.setText("Down");
break;
}
}
}
}
感谢您的宝贵时间!
【问题讨论】:
-
考虑创建并发布sscce。不过,当我看到需要关注的 JPanel 时,这让我感到怀疑。为什么这是必要的?为什么 GUI 类要实现监听器接口?通常,如果将它们分开,您的代码更易于维护。
-
而且布局不应该影响 ActionListener 事件,所以我不得不怀疑其他的东西是否不同或错误。根据您迄今为止提供的信息,我很难判断这就是为什么sscce 会极大地帮助。
-
关于 sscce,我认为我无法将其最小化。文字很模糊,但那是因为我的英语,我不能更短地表达自己(我想)。无论如何,如果您仍然认为它太大而不“简洁”,请告诉我,我会尽力而为。关于 GUI 实现监听器,这是我正在编程的快速俄罗斯方块。没有 MVC 或 Command-Kernel 模式,我猜是“硬代码”。
-
通过这种方式隔离问题并不容易,但我仍然建议您尝试这样做,即使您从未在此处发布代码,因为通常努力会让您看到问题并自己解决。祝你好运!
-
我知道,我真的在努力。谢谢!
标签: java swing layout-manager keylistener grouplayout