在现有的 JPanel 上绘制 JLayeredPane
Posted
技术标签:
【中文标题】在现有的 JPanel 上绘制 JLayeredPane【英文标题】:Drawing in JLayeredPane over exising JPanels 【发布时间】:2011-10-12 06:42:48 【问题描述】:我正在开发一款国际象棋游戏。我想让板容器利用 GridLayout 来显示 8x8 的 JPanel 网格。 (这将使突出选定的方块和有效移动等功能更加容易。)然后我想在这一层上添加碎片,以便可以拖放它们。我最初通过在单个方形 JPanel 中绘制它们来显示这些碎片,但我认为稍后尝试拖放它们时会出现问题。从那以后,我一直在尝试使用 JLayeredPane 作为主容器,但遇到了几个问题。
一旦我为 JLayeredPane 指定了 GridLayout,无论我使用哪个 Integer 来指定要添加 JLabel 或其他类型图像的图层,这些片段都会被添加到网格中,从而设置它们的位置并扭曲整个电路板。我读过使用 LayoutManagers 会干扰 JLayeredPane 上的图层定位,所以这并不奇怪。 (尽管 JLayeredPane 教程中的 Oracle 演示程序似乎可以很好地做到这一点:http://download.oracle.com/javase/tutorial/uiswing/examples/components/LayeredPaneDemo2Project/src/components/LayeredPaneDemo2.java)
但是,我也尝试将 JPanel 的网格放入它自己的 JPanel,然后将其添加到 JLayeredPane 的低层,我的想法是我可以将拖放图标添加到单独的非透明 JPanel在 JLayeredPane 的更高层上。但是,当我这样做时,在 JLayeredPane 中简单地拥有网格 JPanel 之后(即在添加拖放层之前),网格将不会显示。
我也尝试过覆盖 JLayeredPane 的paintComponent(和paint)方法来绘制片段图像,但是它们被 JPanel 隐藏(我可以通过将 JPanel 设置为不透明来看到它们确实存在)和据我所知,没有选项可以在 JLayeredPane 上设置图形图层。我也尝试使用框架的 glassPane 来绘制碎片,但那里也出现了不良行为。
任何帮助解释这种行为,或者我哪里出错了,将不胜感激!
【问题讨论】:
我的回答可以帮助你:***.com/questions/4687607/… 还有这个:***.com/questions/4893265/… 【参考方案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);
【讨论】:
感谢您的提示!如果我几天前发布了这篇文章,你会为我节省大量时间和挫败感。事实证明,在那段时间之后,我刚刚在最后一个小时左右克服了障碍,它正在做你的代码所做的事情——基本上是在没有 LayoutManager 的情况下编写 JLayeredPane 的所有元素。以上是关于在现有的 JPanel 上绘制 JLayeredPane的主要内容,如果未能解决你的问题,请参考以下文章
Swing:如何在每个组件、JPanel、JButton 等上绘制动画?
当我绘制另一个矩形时,如何保留我在 Jpanel 上绘制的矩形?