尝试使用GridLayout在JPanel上移动JLabel [英] Trying to move JLabels on a JPanel with GridLayout

查看:55
本文介绍了尝试使用GridLayout在JPanel上移动JLabel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在JPanel上相互按下按钮,以使JLabels相互交换位置.

I am trying to make some JLabels switch places with eachother on a JPanel with GridLayout on key pressed.

到目前为止:
1.我只能让它们对鼠标单击做出反应.
2.他们只能切换上方和左侧的位置.

So far:
1. I can only make them react to a mouse click.
2. They can only switch places with the one above it and to its left.

注意:
1.如果设置了movePlayer(1),它将起作用.并从网格(8,7)切换JLabel,其中播放器的图像与其中一个JLabel的图像一起在其上方的地板上.但是我的问题是,当我设置movePlayer(2)时,它给了我并且索引超出了bouds异常.
2.这只是我认为与该问题相关的代码的一部分:

Note:
1. If I set movePlayer(1) it works. And switches a JLabel from the grid (8,7) with an image of the player with one of the JLabels with an image of a floor above it. However my problem is, when i set movePlayer(2) it gives me and index out of bouds exception.
2. This is only part of the code which I believe to be relevant to the issue:

  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())填充myMap数组.

1.MapElement is a parent class(inherits) to many subclasses.
2.loadMap() reads out chars (E.g. a,b,c...)from an array of chars to fill the array myMap with a new instance of a subclass of MapElement(E.g. new Player(),new Floor(),new Tree()).

3. drawMap()根据以下类别将JLabels添加到JPanel myMap [i] [j]

3.drawMap() adds JLabels to the JPanel according to the class of of myMap[i][j]

4.(两种方法都使用双For循环i< 8,j< 7(来填充
GridLayout(8,7).

4.(Both methods were done with double For loops i<8, j<7(to fill the
GridLayout(8,7) .

谢谢您,感谢您的编码错误和笨拙,希望您能明白这一点.随意提出一种更好的方式来将玩家(JLabel)GridLayout一起移动到JPanel上.记住,主要问题是:为什么(dir == 1)起作用而(dir == 2)无效?!

Thank you, sorry for the bad coding and noobishness, hope this is clear. Feel free to suggest a better way to move a player (JLabel) on a JPanel with a GridLayout. And remember, the main question is: Why does (dir == 1) work and (dir == 2) doesn't?!

推荐答案

我不确定我是否完全理解您的问题,但是,可以使用一些技巧来更改组件的呈现顺序,例如,您可以更改componentZOrder,这将更改组件的布局和渲染顺序.

I'm not sure I understand your problem entirely, but, there are some tricks you can use to change the order in which components are rendered, for example, you can change the componentZOrder, which will change the order in which the components are laid out and rendered.

如果要包括键盘交互,我强烈建议使用键绑定API ,例如...

If you want to include key board interaction, I highly recommend using the Key Bindings API, for example...

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可以处理垂直和水平更改,您可能要考虑使用两个或多个更改,这样可以更好地限制移动,因此,如果用户尝试移动到行的开头或结尾之外,它会限制它们,如现在所示,它允许组件向上或向下流到下一行

Now, the Action I use handles both vertical and horizontal changes, you might want to consider using two or more, which could better constrain the movement, so if the user tried moving beyond the start or end of the row, it would restrict them, as it stands right now, it allows the component to flow up or down to the next row

您可能还想看看如何使用操作

这篇关于尝试使用GridLayout在JPanel上移动JLabel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆