Java JLayeredPanel布局管理器自由移动对象
我有一个游戏板,有8块,我希望能够将它们移动到jpanel上的任何地方。目前,我只能做流或网格布局,但这并不能产生预期的结果。长期目标是能够独立单击一个工件并将其拖动到所需的位置。(包括在其他部件的顶部) 欢迎您提供任何建议或意见。。。(感谢装满鳗鱼的气垫船,Madschellet,peeskillet,Andrew Thompson,感谢他们早期的建议)Java JLayeredPanel布局管理器自由移动对象,java,swing,jpanel,Java,Swing,Jpanel,我有一个游戏板,有8块,我希望能够将它们移动到jpanel上的任何地方。目前,我只能做流或网格布局,但这并不能产生预期的结果。长期目标是能够独立单击一个工件并将其拖动到所需的位置。(包括在其他部件的顶部) 欢迎您提供任何建议或意见。。。(感谢装满鳗鱼的气垫船,Madschellet,peeskillet,Andrew Thompson,感谢他们早期的建议) 导入java.awt.Component; 导入java.awt.Container; 导入java.awt.Dimension; 导入ja
导入java.awt.Component;
导入java.awt.Container;
导入java.awt.Dimension;
导入java.awt.FlowLayout;
导入java.awt.Image;
导入java.awt.Point;
导入java.awt.event.MouseEvent;
导入java.awt.event.MouseListener;
导入java.awt.event.MouseMotionListener;
导入javax.swing.ImageIcon;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JLayeredPane;
导入javax.swing.JPanel;
公共类FireflyGameBoard扩展JFrame实现MouseListener,
鼠标移动
{
JLayeredPane layeredPane;
JPanel游戏板;
//JPanel背景;
JLabel游戏机;
内部调整;
内部调整;
图像图标;
图像背景;
字符串Rimagepath=“/Users/yournamehere/Documents/workspace/MotionGraphicsTest/resources/”;
公众萤火虫游戏板()
{
尺寸板尺寸=新尺寸(1920、1080);
bgicon=新图像图标(Rimagepath+“Backdroptest.png”);
bg=bgicon.getImage();
ImagePanel背景=新建ImagePanel(新建ImageIcon(Rimagepath
+“Backdroptest.png”).getImage();
//为此应用程序使用分层窗格
layeredPane=新的JLayeredPane();
getContentPane().add(layeredPane);
layeredPane.setPreferredSize(boardSize);
layeredPane.addMouseListener(此);
layeredPane.addMouseMotionListener(此);
//将棋盘添加到分层窗格
gameBoard=新图像面板(bg);
layeredPane.add(背景,JLayeredPane.DEFAULT_层);
layeredPane.add(游戏板,JLayeredPane.MODAL_层);
gameBoard.setLayout(新的FlowLayout());
gameBoard.setPreferredSize(boardSize);
gameBoard.setBounds(0,0,boardSize.width,boardSize.height);
//对于(int i=0;i<64;i++)
// {
//JPanel square=newjpanel(newborderlayout());
//游戏板。添加(方形);
//
////square.setBackground(空);
// }
//在黑板上加几块
JLabel片段=新JLabel(新图像图标(Rimagepath+“alliance.png”);
游戏板。添加(块);
工件=新的JLabel(新的图像图标(Rimagepath+“piece2.png”);
游戏板。添加(块);
工件=新的JLabel(新的图像图标(Rimagepath+“piece3.png”);
游戏板。添加(块);
工件=新的JLabel(新的图像图标(Rimagepath+“piece4.png”);
游戏板。添加(块);
工件=新的JLabel(新的图像图标(Rimagepath+“reaper.png”);
游戏板。添加(块);
工件=新的JLabel(新的图像图标(Rimagepath+“piece6.png”);
游戏板。添加(块);
工件=新的JLabel(新的图像图标(Rimagepath+“piece7.png”);
游戏板。添加(块);
工件=新的JLabel(新的图像图标(Rimagepath+“piece8.png”);
游戏板。添加(块);
}
@凌驾
公共无效鼠标按下(MouseEvent e)
{
gamePiece=null;
Component c=gameBoard.findComponentAt(e.getX(),e.getY());
if(JPanel的c实例)
返回;
Point parentLocation=c.getParent().getLocation();
xAdjustment=parentLocation.x-e.getX();
yAdjustment=parentLocation.y-e.getY();
游戏片=(JLabel)c;
设置位置(e.getX()+xaadjustment,e.getY()+yaadjustment);
gamePiece.setSize(gamePiece.getWidth(),gamePiece.getHeight());
layeredPane.add(gamePiece,JLayeredPane.DRAG_层);
}
//把棋子四处移动
@凌驾
公共无效鼠标标记(MouseEvent me)
{
如果(游戏片==null)
返回;
setLocation(me.getX()+xaadjustment,me.getY()+yaadjustment);
}
//把棋子放回棋盘上
@凌驾
公共无效MouseEvent(MouseEvent e)
{
如果(游戏片==null)
返回;
游戏件。设置可见(假);
Component c=gameBoard.findComponentAt(e.getX(),e.getY());
if(JLabel的c实例)
{
容器父级=c.getParent();
父。删除(0);
添加(游戏件);
}
其他的
{
容器父项=(容器)c;
添加(游戏件);
}
游戏件。设置可见(真);
}
@凌驾
公共无效mouseClicked(MouseEvent e)
{
}
@凌驾
public void mouseMoved(MouseEvent e)
{
}
@凌驾
公共无效鼠标事件(鼠标事件e)
{
}
@凌驾
公共无效mouseExited(MouseEvent e)
{
}
公共静态void main(字符串[]args)
{
JFrame frame=新的FireflyGameBoard();
frame.setDefaultCloseOperation(在关闭时处理);
frame.pack();
frame.setresizeable(true);
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
}
另外,这不是学校的作业,我的g/f是一个狂热的棋盘游戏玩家,我想让她成为一些她最喜欢的游戏的数字版本……拖放是一项严肃的工作。当做得好的时候,它会非常棒,但是要为一些严肃的繁重工作和设计工作做好准备 一种方法是尝试生成自包含的工作单元,即工件负责管理其自身的阻力,单元/网格负责管理下降 拖拉/单件
棋子
是一个可移动的游戏棋子,可以拖动到新位置
工件本身负责管理用于初始化拖动过程的DragGestureRecognizer
因为我想在文章中显示一个图标,所以我选择覆盖JLabel
,因为它提供了这方面的核心功能
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.image.BufferedImage;
import javax.swing.JLabel;
public class PieceLabel extends JLabel {
private DragGestureHandler dragGestureHandler;
private DragGestureRecognizer dgr;
public PieceLabel() {
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
}
@Override
public void addNotify() {
super.addNotify();
if (dgr == null) {
dragGestureHandler = new DragGestureHandler(this);
dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, dragGestureHandler);
}
}
@Override
public void removeNotify() {
if (dgr != null) {
dgr.removeDragGestureListener(dragGestureHandler);
dragGestureHandler = null;
}
dgr = null;
super.removeNotify();
}
public static class DragGestureHandler implements DragGestureListener, DragSourceListener {
private PieceLabel piece;
private Container parent;
public DragGestureHandler(PieceLabel child) {
this.piece = child;
}
public PieceLabel getPiece() {
return piece;
}
protected void setParent(Container parent) {
this.parent = parent;
}
protected Container getParent() {
return parent;
}
@Override
public void dragGestureRecognized(DragGestureEvent dge) {
// When the drag begins, we need to grab a reference to the
// parent container so we can return it if the drop
// is rejected
Container parent = getPiece().getParent();
setParent(parent);
// Remove the panel from the parent. If we don't do this, it
// can cause serialization issues. We could over come this
// by allowing the drop target to remove the component, but that's
// an argument for another day
parent.remove(getPiece());
// Update the display
parent.invalidate();
parent.repaint();
// Create our transferable wrapper
Transferable transferable = new PieceTransferable(getPiece());
// Start the "drag" process...
DragSource ds = dge.getDragSource();
// ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
BufferedImage image = BoardDrag.createBufferedImage(piece.getIcon(), piece);
Point pp = piece.getLocation();
Point dp = dge.getDragOrigin();
int x = image.getWidth() / 2;
int y = image.getHeight() / 2;
ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), image, new Point(x, y), transferable, this);
}
@Override
public void dragEnter(DragSourceDragEvent dsde) {
}
@Override
public void dragOver(DragSourceDragEvent dsde) {
}
@Override
public void dropActionChanged(DragSourceDragEvent dsde) {
}
@Override
public void dragExit(DragSourceEvent dse) {
}
@Override
public void dragDropEnd(DragSourceDropEvent dsde) {
// If the drop was not sucessful, we need to
// return the component back to it's previous
// parent
if (!dsde.getDropSuccess()) {
getParent().add(getPiece());
getParent().invalidate();
getParent().repaint();
}
}
}
}
放置/单元/网格
单元/网格就是这样,它在整个网格/bo中构成一个元素
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.image.BufferedImage;
import javax.swing.JLabel;
public class PieceLabel extends JLabel {
private DragGestureHandler dragGestureHandler;
private DragGestureRecognizer dgr;
public PieceLabel() {
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
}
@Override
public void addNotify() {
super.addNotify();
if (dgr == null) {
dragGestureHandler = new DragGestureHandler(this);
dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, dragGestureHandler);
}
}
@Override
public void removeNotify() {
if (dgr != null) {
dgr.removeDragGestureListener(dragGestureHandler);
dragGestureHandler = null;
}
dgr = null;
super.removeNotify();
}
public static class DragGestureHandler implements DragGestureListener, DragSourceListener {
private PieceLabel piece;
private Container parent;
public DragGestureHandler(PieceLabel child) {
this.piece = child;
}
public PieceLabel getPiece() {
return piece;
}
protected void setParent(Container parent) {
this.parent = parent;
}
protected Container getParent() {
return parent;
}
@Override
public void dragGestureRecognized(DragGestureEvent dge) {
// When the drag begins, we need to grab a reference to the
// parent container so we can return it if the drop
// is rejected
Container parent = getPiece().getParent();
setParent(parent);
// Remove the panel from the parent. If we don't do this, it
// can cause serialization issues. We could over come this
// by allowing the drop target to remove the component, but that's
// an argument for another day
parent.remove(getPiece());
// Update the display
parent.invalidate();
parent.repaint();
// Create our transferable wrapper
Transferable transferable = new PieceTransferable(getPiece());
// Start the "drag" process...
DragSource ds = dge.getDragSource();
// ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), transferable, this);
BufferedImage image = BoardDrag.createBufferedImage(piece.getIcon(), piece);
Point pp = piece.getLocation();
Point dp = dge.getDragOrigin();
int x = image.getWidth() / 2;
int y = image.getHeight() / 2;
ds.startDrag(dge, Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR), image, new Point(x, y), transferable, this);
}
@Override
public void dragEnter(DragSourceDragEvent dsde) {
}
@Override
public void dragOver(DragSourceDragEvent dsde) {
}
@Override
public void dropActionChanged(DragSourceDragEvent dsde) {
}
@Override
public void dragExit(DragSourceEvent dse) {
}
@Override
public void dragDropEnd(DragSourceDropEvent dsde) {
// If the drop was not sucessful, we need to
// return the component back to it's previous
// parent
if (!dsde.getDropSuccess()) {
getParent().add(getPiece());
getParent().invalidate();
getParent().repaint();
}
}
}
}
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class Cell extends JPanel {
private DropTarget dropTarget;
private DropHandler dropHandler;
public Cell() {
setLayout(new BorderLayout());
}
@Override
public void addNotify() {
super.addNotify();
if (dropHandler == null) {
dropHandler = new DropHandler();
}
if (dropTarget == null) {
dropTarget = new DropTarget(this, DnDConstants.ACTION_MOVE, dropHandler, true);
}
}
@Override
public void removeNotify() {
if (dropTarget != null) {
dropTarget.removeDropTargetListener(dropHandler);
}
dropTarget = null;
dropHandler = null;
super.removeNotify();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(48, 48);
}
public class DropHandler implements DropTargetListener {
@Override
public void dragEnter(DropTargetDragEvent dtde) {
// Determine if can actual process the contents comming in.
// You could try and inspect the transferable as well, but
// There is an issue on the MacOS under some circumstances
// where it does not actually bundle the data until you accept the
// drop.
if (dtde.isDataFlavorSupported(PieceDataFlavor.SHARED_INSTANCE)) {
dtde.acceptDrag(DnDConstants.ACTION_MOVE);
} else {
dtde.rejectDrag();
}
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
@Override
public void dragExit(DropTargetEvent dte) {
}
@Override
public void drop(DropTargetDropEvent dtde) {
boolean success = false;
// Basically, we want to unwrap the present...
if (dtde.isDataFlavorSupported(PieceDataFlavor.SHARED_INSTANCE)) {
Transferable transferable = dtde.getTransferable();
try {
Object data = transferable.getTransferData(PieceDataFlavor.SHARED_INSTANCE);
if (data instanceof PieceLabel) {
PieceLabel piece = (PieceLabel) data;
DropTargetContext dtc = dtde.getDropTargetContext();
Component component = dtc.getComponent();
if (component instanceof JComponent) {
Container parent = piece.getParent();
if (parent != null) {
parent.remove(piece);
}
((JComponent) component).add(piece);
success = true;
dtde.acceptDrop(DnDConstants.ACTION_MOVE);
invalidate();
repaint();
} else {
success = false;
dtde.rejectDrop();
}
} else {
success = false;
dtde.rejectDrop();
}
} catch (Exception exp) {
success = false;
dtde.rejectDrop();
exp.printStackTrace();
}
} else {
success = false;
dtde.rejectDrop();
}
dtde.dropComplete(success);
}
}
}
import java.awt.datatransfer.DataFlavor;
public class PieceDataFlavor extends DataFlavor {
public static final PieceDataFlavor SHARED_INSTANCE = new PieceDataFlavor();
public PieceDataFlavor() {
super(PieceLabel.class, null);
}
}
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
public class PieceTransferable implements Transferable {
private final DataFlavor[] flavors = new DataFlavor[]{PieceDataFlavor.SHARED_INSTANCE};
private final PieceLabel piece;
public PieceTransferable(PieceLabel piece) {
this.piece = piece;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
// Okay, for this example, this is over kill, but makes it easier
// to add new flavor support by subclassing
boolean supported = false;
for (DataFlavor mine : getTransferDataFlavors()) {
if (mine.equals(flavor)) {
supported = true;
break;
}
}
return supported;
}
public PieceLabel getPanel() {
return piece;
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
Object data = null;
if (isDataFlavorSupported(flavor)) {
data = getPanel();
} else {
throw new UnsupportedFlavorException(flavor);
}
return data;
}
}
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class BoardPane extends JPanel {
public BoardPane() {
setLayout(new GridLayout(8, 8));
int index = 0;
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Cell cell = new Cell();
if (index % 2 == 0) {
cell.setBackground(Color.WHITE);
} else {
cell.setBackground(Color.BLACK);
}
add(cell);
index++;
}
index++;
}
try {
PieceLabel label = new PieceLabel();
BufferedImage image = ImageIO.read(getClass().getResource("/Piece01.png"));
label.setIcon(new ImageIcon(image));
setCellPiece(label, 0, 0);
} catch (IOException ex) {
Logger.getLogger(BoardDrag.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void setCellPiece(PieceLabel label, int row, int col) {
int index = (row * 8) + col;
Cell cell = (Cell) getComponent(index);
cell.removeAll();
cell.add(label);
}
}