【问题标题】:Trying to move JLabels on a JPanel with GridLayout尝试使用 GridLayout 在 JPanel 上移动 JLabels
【发布时间】:2016-01-04 05:46:08
【问题描述】:

我正在尝试让一些 JLabels 在 JPanel 上相互交换位置,并在按键时使用 GridLayout。

到目前为止:
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() 从字符数组中读出字符(例如 a,b,c...),以使用 MapElement 子类的新实例(例如 new Player(),new Floor(),new Tree())填充数组 myMap。

3.drawMap() 根据类将JLabels 添加到JPanel 我的地图[i][j]

4.(两种方法都使用双 For 循环 iGridLayout(8,7)

谢谢你,对糟糕的编码和noobishness感到抱歉,希望这很清楚。随意提出一个更好的方法来移动玩家(JLabel)JPanelGridLayout。请记住,主要问题是:为什么(dir == 1) 有效而(dir == 2) 无效?!

【问题讨论】:

  • 考虑提供一个runnable example 来证明您的问题。这不是代码转储,而是您正在做的事情的一个示例,它突出了您遇到的问题。这将导致更少的混乱和更好的响应

标签: java swing loops jlabel


【解决方案1】:

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

如果你想包含键盘交互,我强烈推荐使用Key Bindings 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 我使用处理垂直和水平变化,您可能需要考虑使用两个或更多,这样可以更好地限制移动,所以如果用户尝试移动超出行的开头或结尾,它会限制它们,就像现在一样,它允许组件向上或向下流动到下一行

您可能还想看看How to Use Actions

【讨论】:

    猜你喜欢
    • 2014-12-04
    • 2013-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多