[英]Trying to move JLabels on a JPanel with GridLayout
我正在尝试在JPanel上通过按键按下GridLayout在JPanel上互相设置一些JLabels开关位置。
至今:
1.我只能让他们对鼠标单击做出反应。
2.他们只能切换上方和左侧的位置。
注意:
1.如果设置了movePlayer(1),它将起作用。 并从网格(8,7)切换JLabel,其中播放器的图像与其中一个JLabel的图像在其上方的地板上。 但是我的问题是,当我设置movePlayer(2)时,它给了我并且索引超出了bouds异常。
2.这只是我认为与该问题相关的代码的一部分:
JPanel myCentrePanel = new JPanel();
MapElement[][] myMap = new MapElement[8][7];
public TileSwitching(){
super("TileSwitching");
setSize(400,400);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
myCentrePanel.setLayout(new GridLayout(8,7));
myCentrePanel.setPreferredSize(new Dimension(5,5));
add(myCentrePanel);
loadMap(level1);
drawMap();
myCentrePanel.setFocusable(true);
myCentrePanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
movePlayer(1);
myCentrePanel.removeAll();
drawMap();
myCentrePanel.revalidate();
}
});
myCentrePanel.setBackground(Color.CYAN);
}
public void movePlayer(int dir){
if(dir == 1){
for(int i = 0; i<8; i++){
for(int j= 0; j<7; j++){
if (myMap[i][j].getClass() == wk.getClass()){
myMap[i-1][j] = new Player();
myMap[i][j] = new Floor();
}
else{
myMap[i][j] = myMap[i][j];
}
}}
if(dir == 2){
for(int i = 0; i<8; i++){
for(int j= 0; j<7; j++){
if (myMap[i][j].getClass() == wk.getClass()){
myMap[i+1][j] = new Player();
myMap[i][j] = new Floor();
}
else{
myMap[i][j] = myMap[i][j];
}
}}
}
public static void main(String[] args) {
TileSwitching tl = new TileSwitching();
TileSwitching.setVisible(true);
}
上面的代码未显示什么:
1. MapElement
是许多子类的父类(继承)。
2. loadMap()
从char数组中读取chars(例如a,b,c ...),以使用MapElement的子类的新实例(例如new Player(),new Floor(),new Tree()
)。
3. drawMap()
根据myMap [i] [j]的类将JLabels
添加到JPanel
4.(这两种方法都是用两个For循环i <8,j <7(
GridLayout(8,7)
。
谢谢,不好意思的编码和笨拙,希望这很清楚。 请随意提出一个更好的方法,用GridLayout
在JPanel
上移动播放器(JLabel)
。 记住,主要问题是:为什么(dir == 1)
起作用而(dir == 2)
不起作用?
我不确定我是否完全理解您的问题,但是,您可以使用一些技巧来更改组件的呈现顺序,例如,可以更改componentZOrder
,这将更改组件的放置顺序和渲染。
如果要包括键盘交互,我强烈建议您使用键盘绑定API ,例如...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel player;
private List<JLabel> tiles;
public TestPane() {
setLayout(new GridLayout(3, 3));
player = makeLabel("P");
add(player);
tiles = new ArrayList<>(8);
for (int index = 0; index < 8; index++) {
JLabel tile = makeLabel(" ");
tiles.add(tile);
add(tile);
}
addKeyBinding("left", KeyEvent.VK_LEFT, new MoveAction(-1, 0));
addKeyBinding("right", KeyEvent.VK_RIGHT, new MoveAction(1, 0));
addKeyBinding("up", KeyEvent.VK_UP, new MoveAction(0, -1));
addKeyBinding("down", KeyEvent.VK_DOWN, new MoveAction(0, 1));
}
protected void addKeyBinding(String name, int keyCode, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(KeyStroke.getKeyStroke(keyCode, 0), name);
actionMap.put(name, action);
}
protected JLabel makeLabel(String text) {
JLabel label = new JLabel(text);
label.setBorder(new CompoundBorder(
new LineBorder(Color.GRAY),
new EmptyBorder(4, 4, 4, 4)));
return label;
}
public class MoveAction extends AbstractAction {
private final int xDelta, yDelta;
public MoveAction(int xDelta, int yDelta) {
this.xDelta = xDelta;
this.yDelta = yDelta;
}
@Override
public void actionPerformed(ActionEvent e) {
int index = getComponentZOrder(player);
index += xDelta;
index += (yDelta * 3);
if (index < 0) {
index = 0;
} else if (index >= getComponentCount()) {
index = getComponentCount() - 1;
}
setComponentZOrder(player, index);
revalidate();
repaint();
}
}
}
}
现在,我使用的Action
既可以处理垂直变化也可以处理水平变化,您可能需要考虑使用两个或多个,这样可以更好地限制移动,因此,如果用户尝试移动到行的开头或结尾之外,则会对其进行限制,就目前而言,它允许组件向上或向下流动到下一行
您可能还想看看如何使用动作
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.