【问题标题】:Resize layer of JLayeredPane调整 JLayeredPane 图层的大小
【发布时间】:2012-09-05 17:31:15
【问题描述】:

我在尝试使用 JLayeredPane 制作自己的国际象棋游戏时遇到问题。

我已经走到这一步了:

(希望你能看到区块G6的标签上有一个绿色边框,显示选择了哪个区块)

但是,当我将我的 2 个 SidePanels 添加到我的 ChessBoard 面板,然后在顶部再添加一层标签时,应该完全覆盖每个板块,但它没有:

如您所见,G2 块周围的绿色边框已关闭。

当我将SidePanels 添加到ChessBoard 并将其添加到底层并将其大小设置为 600x600 然后添加顶层,这是适合ChessBoard 的块,绿色边框围绕选定的JLabel(以及较低的ChessBoard 正方形[黑色或白色])绘制,由于SidePanels 已经减少,它被绘制偏离中心棋盘的实际大小为 600x600,现在是600-sp1.getWidth()x600-sp2.getHeight()。我尝试设置顶层的边界和首选大小来补偿它,但它似乎没有用。感谢您的任何帮助:

ChessBoardTest.java:

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashMap;
import javax.swing.*;
import javax.swing.border.BevelBorder;

public class ChessBoardTest {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                Dimension boardSize = new Dimension(600, 600);

                JFrame frame = new JFrame("Chess JLayeredPane Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setResizable(false);

                Container contentPane = frame.getContentPane();

                ChessBoard chessBoard = new ChessBoard();
                SidePanel sp1 = new SidePanel(new String[]{"8", "7", "6", "5", "4", "3", "2", "1"}, SidePanel.VERTICAL);
                SidePanel sp2 = new SidePanel(new String[]{"A", "B", "C", "D", "E", "F", "G", "H"}, SidePanel.HORIZONTAL);

                //adding these 2 side panels messes up the layout
                chessBoard.add(sp1, BorderLayout.WEST);
                chessBoard.add(sp2, BorderLayout.SOUTH);

                chessBoard.setPreferredSize(boardSize);
                chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);

                ChessPieceLayer chessPieceLayer = new ChessPieceLayer();

            //chessPieceLayer.setPreferredSize(boardSize);
            //chessPieceLayer.setBounds(0, 0, boardSize.width, boardSize.height);

            //i've tried resizing to make up for the side panels but no result
            chessPieceLayer.setPreferredSize(new Dimension(600-sp1.getWidth(),600-sp2.getHeight()));
            chessPieceLayer.setBounds(0+sp1.getWidth(), 0+sp2.getHeight(), 600-sp1.getWidth(), 600-sp2.getHeight());




                JLayeredPane jLayeredPane = new JLayeredPane();
                jLayeredPane.setPreferredSize(boardSize);

                jLayeredPane.add(chessBoard, JLayeredPane.FRAME_CONTENT_LAYER);
                jLayeredPane.add(chessPieceLayer, JLayeredPane.MODAL_LAYER);

                contentPane.add(jLayeredPane);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

SidePanel.java:

class SidePanel extends JPanel {

    final static String HORIZONTAL = "horizontal";
    final static String VERTICAL = "vertical";

    public SidePanel(String[] strings, String direction) {
        if (direction.equals(VERTICAL)) {
            setLayout(new GridLayout(8, 0));
        } else {
            setLayout(new GridLayout(0, 8));
        }
        setDoubleBuffered(true);
        for (String string : strings) {
            this.add(new JLabel(string, JLabel.CENTER));
        }

    }
}

ChessBoard.java:

class ChessBoard extends JPanel {

    public ChessBoard() {
        super(new BorderLayout(), true);

        this.add(populateBoard(Color.white, Color.black), BorderLayout.CENTER);
    }

    private JPanel populateBoard(Color c1, Color c2) {
        JPanel panel = new JPanel(new GridLayout(8, 8));
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                JPanel square = new JPanel(new BorderLayout());
                square.setBackground((i + j) % 2 == 0 ? c1 : c2);
                panel.add(square);
            }
        }
        return panel;
    }
}

ChessPieceLayer.java:

class ChessPieceLayer extends JComponent {

    private HashMap<PiecePanel, String> panelsMap = new HashMap<>(64);
    final ChessPieceMouseListener listener;

    ChessPieceLayer() {
        super();
        listener = new ChessPieceMouseListener();
        setLayout(new GridLayout(8, 8));
        setDoubleBuffered(true);

        fillPanelsMap();
    }

    private void fillPanelsMap() {
        String[] cols = new String[]{"A", "B", "C", "D", "E", "F", "G", "H"};
        int[] rows = new int[]{1, 2, 3, 4, 5, 6, 7, 8};
        String row, col;
        int rowCount = 7, colCount = 0, trigger = 8;

        for (int i = 0; i < 64; i++) {

            if (trigger == 0) {
                colCount = 0;
                trigger = 8;
                rowCount--;
            }
            col = cols[colCount++];
            row = rows[rowCount] + "";
            trigger--;

            String location = col + row;

            PiecePanel square = createAndAddPiecesWithMouseListener(location);

            panelsMap.put(square, location);

        }
    }

    private PiecePanel createAndAddPiecesWithMouseListener(String location) {
        PiecePanel square = new PiecePanel(location, JLabel.CENTER);
        square.addMouseListener(listener);
        square.setText(location);
        this.add(square);
        return square;
    }
}

PiecePanel.java:

class PiecePanel extends JLabel {

    private String location;

    public PiecePanel(String text, int horizontalAlignment) {
        super("", horizontalAlignment);
        this.location = text;
    }

    PiecePanel(String location) {
        this.location = location;
    }

    public String getPieceLocation() {
        return location;
    }

    public void setPieceLocation(String location) {
        this.location = location;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
    }
}

ChessPieceMouseListener.java:

class ChessPieceMouseListener implements MouseListener {

    int counter = 0;
    PiecePanel this_pp, prev_pp;

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        PiecePanel pp = (PiecePanel) e.getComponent();
        if (counter == 0) {
            this_pp = pp;
            this_pp.setBorder(new BevelBorder(0, Color.green, Color.green));
            JOptionPane.showMessageDialog(null, "From " + pp.getPieceLocation());
            counter = 1;
        } else {
            prev_pp = this_pp;
            this_pp = pp;
            prev_pp.setBorder(null);
            JOptionPane.showMessageDialog(null, "To " + pp.getPieceLocation());
            counter = 0;
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }
}

一开始我用的是:

chessPieceLayer.setPreferredSize(boardSize);
chessPieceLayer.setBounds(0, 0, boardSize.width, boardSize.height);

然后我尝试了:   

chessPieceLayer.setPreferredSize(new Dimension(600-sp1.getWidth(),600-sp2.getHeight()));
chessPieceLayer.setBounds(0+sp1.getWidth(), 0+sp2.getHeight(), 600-sp1.getWidth(), 600-sp2.getHeight());

但结果没有区别

【问题讨论】:

  • 能把Chessboard和ChessPiecePlayer的代码贴出来吗?
  • @GuillaumePolet 都在那里。正在使用内部类,因此它们当然不会在自己的文件中声明用于测试。但我现在把它分开了,以便于查看
  • 另见example和variation。

标签: java swing java-7 jlayeredpane jlayer


【解决方案1】:

好的,我找到了问题,并且有一个简单的解决方案。下一次,尝试将您的代码放在一个类中,这样我就不必做太多的复制/粘贴(这种阻止人们尝试您的代码);-)。

无论如何,问题来自您的 SidePanel,它占用了 ChessBoardPanel 上的空间,因此引入了偏移量。解决方法很简单,你要做的就是:

  1. 将sp1 和sp2 添加到contentPane
  2. 在您的 chessBoard 和 chessPieceLayer 上只需将大小设置为 boardSize。

解释

  1. 我们将 SidePanel 移至内容窗格,这样它们就不会干扰您的图层。当您使用 JLayeredPane 时,您使用所谓的绝对布局或空布局。这意味着您必须注意组件的定位和大小。这让我想到了第 2 点:
  2. 当没有LayoutManager 时,设置preferredSize 是没有用的,因为没有LayoutManager 可以调用该方法。现在,默认组件位于 (0,0) 中,因此您只需调用 setSize。如果您希望它们被偏移,您还需要调用setLocation,或者将这两个调用连接到一个调用setBounds

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 2017-09-19
    • 2020-02-09
    相关资源
    最近更新 更多