Рисование в JLayeredPane поверх существующих JPanels
Я работаю над разработкой игры в шахматы. Я хочу, чтобы Контейнер доски использовал GridLayout для отображения сетки JPanels 8x8. (Это значительно упростит такие функции, как выделение выделенных квадратов и правильные перемещения.) Затем я хотел бы добавить фигуры поверх этого слоя, чтобы их можно было перетаскивать. Сначала я показывал фрагменты, рисуя их в отдельных квадратных JPanels, но подумал, что это будет проблемой при попытке перетаскивания их позже. С тех пор я пытался использовать JLayeredPane в качестве основного контейнера, но столкнулся с несколькими проблемами.
Во-первых, после того, как я определил GridLayout для JLayeredPane, независимо от того, какое целое число я использую, чтобы указать слой для добавления JLabel или другого вида изображения, части добавляются в сетку, устанавливая их позиции и искажая их. вся доска. Я читал, что использование LayoutManager может помешать позиционированию слоя на JLayeredPane, так что это не слишком удивительно. (Хотя демонстрационная программа Oracle из учебника JLayeredPane, кажется, делает это просто отлично: http://download.oracle.com/javase/tutorial/uiswing/examples/components/LayeredPaneDemo2Project/src/components/LayeredPaneDemo2.java)
Однако я также попытался поместить сетку JPanels в свою собственную JPanel, а затем добавить ее в нижний слой JLayeredPane. Идея заключалась в том, что я мог бы добавлять значки перетаскивания в отдельные непрозрачные JPanel на более высоких слой JLayeredPane. Однако, когда я делаю это, после того, как у меня просто будет сетка JPanel внутри JLayeredPane (т.е. до добавления слоя перетаскивания), сетка не будет отображаться.
Я также попытался переопределить методы paintComponent (и paint) в JLayeredPane для рисования кусочных изображений, но они скрыты JPanels (я вижу, что они действительно есть, установив JPanels в непрозрачный) и насколько Я могу сказать, что нет никакой возможности установить слой графики на JLayeredPane. Я также пытался использовать стеклянную панель рамки для рисования кусочков, но там также получалось нежелательное поведение.
Любая помощь, объясняющая некоторые из этих действий, или где я иду не так, была бы очень признательна!
1 ответ
Вот простой пример, который показывает, как вы можете (случайным образом) перетащить "шахматную фигуру" из одного квадрата в другой:
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);
}
}