问题描述
我正在开发一款国际象棋游戏.我想让板容器利用 GridLayout 来显示 8x8 的 JPanel 网格.(这将使突出显示选定方块和有效移动等功能变得更加容易.)然后我想在这一层上添加碎片,以便可以拖放它们.我最初通过在单独的方形 JPanel 中绘制它们来显示这些碎片,但我认为稍后尝试拖放它们时会出现问题.从那以后,我一直在尝试使用 JLayeredPane 作为主容器,但遇到了几个问题.
I am working on developing a Chess game. I want to have the board Container utilize a GridLayout to display an 8x8 grid of JPanels. (This will make functions such as highlighting selected squares and valid moves much easier.) I would then like to add the pieces over this layer so that they may be dragged and dropped. I initially had the pieces showing by drawing them in the individual square JPanels, but figured that would be a problem when trying to drag-and-drop them later. I have since been trying to use a JLayeredPane as the main container, but have encountered several issues.
一旦我为 JLayeredPane 指定了 GridLayout,无论我使用哪个 Integer 来指定要添加 JLabel 或其他类型图像的图层,这些片段都会被添加到网格中,从而设置它们的位置并扭曲整个电路板.我读过使用 LayoutManagers 会干扰 JLayeredPane 上的图层定位,所以这并不奇怪.(尽管 JLayeredPane 教程中的 Oracle 演示程序似乎可以很好地做到这一点:http://download.oracle.com/javase/tutorial/uiswing/examples/components/LayeredPaneDemo2Project/src/components/LayeredPaneDemo2.java)
One is that once I've specified the GridLayout for the JLayeredPane, regardless of which Integer I use to specify the layer to add the JLabel or other kind of image to, the pieces get added to the grid, making their positions set and and distorting the whole board. I have read that using LayoutManagers can interfere with layer positioning on the JLayeredPane, so this isn't too surprising. (Although the Oracle demo program from the JLayeredPane tutorial seems to do this just fine: http://download.oracle.com/javase/tutorial/uiswing/examples/components/LayeredPaneDemo2Project/src/components/LayeredPaneDemo2.java)
但是,我也尝试将 JPanel 的网格放入它自己的 JPanel,然后将其添加到 JLayeredPane 的低层,我的想法是我可以添加拖动 &将图标拖放到 JLayeredPane 更高层上的单独、非透明 JPanel.但是,当我这样做时,在 JLayeredPane 中简单地拥有网格 JPanel 之后(即在添加拖放层之前),网格将不会显示.
However, I have also tried to put the grid of JPanels into its own JPanel, then add it to a low layer of the JLayeredPane, the idea being that I could add the drag & drop icons to separate, non-opaque JPanel on a higher layer of the JLayeredPane. When I do this however, after I simply have the grid JPanel inside the JLayeredPane (i.e. before the drag-and-drop layer is added), the grid will not display.
我也尝试过覆盖 JLayeredPane 的paintComponent(和paint)方法来绘制片段图像,但它们被JPanels 隐藏(我可以通过将JPanels 设置为非透明来看到它们确实存在)和据我所知,没有在 JLayeredPane 上设置图形图层的选项.我也尝试使用框架的 glassPane 来绘制碎片,但那里也出现了不良行为.
I also have tried overriding the paintComponent (and paint) methods of the JLayeredPane to draw the piece images, but they are hidden by the JPanels (I can see that they are indeed there by setting the JPanels to non-opaque) and as far as I can tell there is no option to set the layer of the graphics on the JLayeredPane. I have also tried using the glassPane of the frame to draw the pieces, but got undesired behavior there as well.
任何帮助解释这种行为,或者我哪里出错了,将不胜感激!
Any help explaining some of this behavior, or where I am going wrong, would be much appreciated!
推荐答案
这是一个简单的例子,展示了如何(随机)将棋子"从一个方格拖放到另一个方格:
Here is a simple example that shows how you might (randomly) drag and drop a "chess piece" from one square to another:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class ChessBoard extends JFrame implements MouseListener, MouseMotionListener
{
JLayeredPane layeredPane;
JPanel chessBoard;
JLabel chessPiece;
int xAdjustment;
int yAdjustment;
public ChessBoard()
{
Dimension boardSize = new Dimension(600, 600);
// Use a Layered Pane for this this application
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize( boardSize );
layeredPane.addMouseListener( this );
layeredPane.addMouseMotionListener( this );
getContentPane().add(layeredPane);
// Add a chess board to the Layered Pane
chessBoard = new JPanel();
chessBoard.setLayout( new GridLayout(8, 8) );
chessBoard.setPreferredSize( boardSize );
chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER);
// Build the Chess Board squares
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 ? Color.red : Color.white );
chessBoard.add( square );
}
}
// Add a few pieces to the board
ImageIcon duke = new ImageIcon("dukewavered.gif"); // add an image here
JLabel piece = new JLabel( duke );
JPanel panel = (JPanel)chessBoard.getComponent( 0 );
panel.add( piece );
piece = new JLabel( duke );
panel = (JPanel)chessBoard.getComponent( 15 );
panel.add( piece );
}
/*
** Add the selected chess piece to the dragging layer so it can be moved
*/
public void mousePressed(MouseEvent e)
{
chessPiece = null;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
if (c instanceof JPanel) return;
Point parentLocation = c.getParent().getLocation();
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY();
chessPiece = (JLabel)c;
chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
layeredPane.add(chessPiece, JLayeredPane.DRAG_LAYER);
layeredPane.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
/*
** Move the chess piece around
*/
public void mouseDragged(MouseEvent me)
{
if (chessPiece == null) return;
// The drag location should be within the bounds of the chess board
int x = me.getX() + xAdjustment;
int xMax = layeredPane.getWidth() - chessPiece.getWidth();
x = Math.min(x, xMax);
x = Math.max(x, 0);
int y = me.getY() + yAdjustment;
int yMax = layeredPane.getHeight() - chessPiece.getHeight();
y = Math.min(y, yMax);
y = Math.max(y, 0);
chessPiece.setLocation(x, y);
}
/*
** Drop the chess piece back onto the chess board
*/
public void mouseReleased(MouseEvent e)
{
layeredPane.setCursor(null);
if (chessPiece == null) return;
// Make sure the chess piece is no longer painted on the layered pane
chessPiece.setVisible(false);
layeredPane.remove(chessPiece);
chessPiece.setVisible(true);
// The drop location should be within the bounds of the chess board
int xMax = layeredPane.getWidth() - chessPiece.getWidth();
int x = Math.min(e.getX(), xMax);
x = Math.max(x, 0);
int yMax = layeredPane.getHeight() - chessPiece.getHeight();
int y = Math.min(e.getY(), yMax);
y = Math.max(y, 0);
Component c = chessBoard.findComponentAt(x, y);
if (c instanceof JLabel)
{
Container parent = c.getParent();
parent.remove(0);
parent.add( chessPiece );
parent.validate();
}
else
{
Container parent = (Container)c;
parent.add( chessPiece );
parent.validate();
}
}
public void mouseClicked(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public static void main(String[] args)
{
JFrame frame = new ChessBoard();
frame.setDefaultCloseOperation( DISPOSE_ON_CLOSE );
frame.setResizable( false );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
这篇关于在现有的 JPanel 上绘制 JLayeredPane的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!