How to add Player to Maze - java

I have constructed a maze and made a player class. When I compile it, I only see the maze and not the player. I have tried different techniques and still it doesn't work for me.
What exactly do I have to do in order to see the player and be able to move it?
Also, is there a way to adjust the maze and make it bigger or same size as frame?
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // Needed for ActionListener
import javax.swing.event.*; // Needed for ActionListener
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
class www extends JFrame
{
static Maze maze = new Maze ();
static Timer t;
//======================================================== constructor
public www ()
{
// 1... Create/initialize components
// 2... Create content pane, set layout
JPanel content = new JPanel (); // Create a content pane
content.setLayout (new BorderLayout ()); // Use BorderLayout for panel
JPanel north = new JPanel ();
north.setLayout (new FlowLayout ()); // Use FlowLayout for input area
DrawArea board = new DrawArea (500, 500);
// 3... Add the components to the input area.
content.add (north, "North"); // Input area
content.add (board, "South"); // Output area
// 4... Set this window's attributes.
setContentPane (content);
pack ();
setTitle ("MAZE");
setSize (490, 500);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo (null); // Center window.
}
public static void main (String[] args)
{
www window = new www ();
window.setVisible (true);
player p = new player ();
JFrame jf = new JFrame ();
//jf.setTitle("Tutorial");
//jf.setSize(600,400);
jf.setVisible(true);
}
class DrawArea extends JPanel
{
public DrawArea (int width, int height)
{
this.setPreferredSize (new Dimension (width, height)); // size
}
public void paintComponent (Graphics g)
{
maze.show (g); // display current state of colony
}
}
}
class Maze
{
private int grid [][];
public Maze ()
{
int [][] maze =
{ {1,0,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,0,1,0,1,0,0,0,0,0,1},
{1,0,1,0,0,0,1,0,1,1,1,0,1},
{1,0,0,0,1,1,1,0,0,0,0,0,1},
{1,0,1,0,0,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,0,0,1},
{1,0,1,0,1,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,1,0,1},
{1,0,0,0,0,0,0,0,0,0,1,0,1},
{1,1,1,1,1,1,1,1,1,1,1,0,1}};
grid = maze;
}
public void show (Graphics g)
{
for (int row = 0 ; row < grid.length ; row++)
for (int col = 0 ; col < grid [0].length ; col++)
{
if (grid [row] [col] == 1) // life
g.setColor (Color.black);
else
g.setColor (Color.white);
g.fillRect (col * 30 + 30, row * 30 + 30, 30, 30); // draw life form
}
}
public class player extends JPanel implements ActionListener,KeyListener
{
Timer tm = new Timer(5,this);
private int x = 0;
private int y = 0;
private int velX = 0 ;
private int velY = 0;
public void player ()
{
tm.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent (Graphics g)
{
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(20,30,50,50);
}
public void actionPerformed(ActionEvent e)
{
x = x+velX;
y = y +velY;
repaint();
}
public void keyPressed(KeyEvent e)
{
int c = e.getKeyCode();
if(c == KeyEvent.VK_LEFT)
{
velX = -1;
velY = 0;
}
if (c == KeyEvent.VK_UP)
{
velX = 0;
velY = -1;
}
if( c==KeyEvent.VK_RIGHT)
{
velX = 1;
velY = 0;
}
if(c==KeyEvent.VK_DOWN)
{
velX = 0;
velY = 1;
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
}
}

Related

Draw shapes with delay

I know there are already hundreds of threads but I just cant understand it..
I have this very simple class thats drawing a grid. I would like to add like a 0.2 second delay after each square. Thread.sleep doesnt work. What is the simplest way?
public Screen() {
repaint();
}
public void paint(Graphics g) {
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
g.drawRect(50 * i, 50 * j, 50, 50);
//Add delay
}
}
}
The simplest way to achieve delayed drawing is by using a Swing Timer, which is a class that won't block the EDT when executed. This will allow you to create a delay without blocking your UI (and making everything appear at once).
You'll have a single JPanel that's going to handle the painting in the paintComponent(...) method and not paint(...) as you did in your code above. This JPanel will repaint every Rectangle shape from the Shape API.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class DelayedDrawing {
private JFrame frame;
private JPanel pane;
private Timer timer;
private int xCoord = 0;
private int yCoord = 0;
private static final int GAP = 10;
private static final int WIDTH_HEIGHT = 10;
private static final int ROWS = 5;
private static final int COLS = 5;
private List<Rectangle> rectangles;
#SuppressWarnings("serial")
private void createAndShowGUI() {
//We create the JFrame
frame = new JFrame(this.getClass().getSimpleName());
//We create a list of Rectangles from the Shape API
rectangles = new ArrayList<>();
createRectangle();
//Creates our JPanel that's going to draw every rectangle
pane = new JPanel() {
//Specifies the size of our JPanel
#Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}
//This is where the "magic" happens, it iterates over our list and repaints every single Rectangle in it
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (Rectangle r : rectangles) {
System.out.println(r.x + " " + r.y);
g2d.draw(r);
}
}
};
//This starts our Timer
timer = new Timer(200, listener);
timer.setInitialDelay(1000);
timer.start();
//We add everything to the frame
frame.add(pane);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//Creates a new Rectangle and adds it to the List
private void createRectangle() {
Rectangle r = new Rectangle(xCoord * WIDTH_HEIGHT + GAP, yCoord * WIDTH_HEIGHT + GAP, WIDTH_HEIGHT, WIDTH_HEIGHT);
rectangles.add(r);
}
//This will be executed everytime the Timer is fired
private ActionListener listener = e -> {
if (xCoord < ROWS) {
if (yCoord < COLS) {
yCoord++;
} else {
yCoord = 0;
xCoord++;
if (xCoord == ROWS) {
timer.stop();
return;
}
}
}
createRectangle();
pane.repaint();
};
public static void main(String[] args) {
SwingUtilities.invokeLater(new DelayedDrawing()::createAndShowGUI);
}
}

How to add player movement [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I made a maze and added a red square to represent player. What do I have to do in order to implement and allow user to move through my maze? What I did before was create a separate class that extends JPanel and implements actionListener but that didn't work out. So I am looking for an alternative method and something that is more easier to establish
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // Needed for ActionListener
import javax.swing.event.*; // Needed for ActionListener
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class www extends JFrame
{
static Maze maze = new Maze ();
static Timer t;
//======================================================== constructor
public www ()
{
// 1... Create/initialize components
// 2... Create content pane, set layout
JPanel content = new JPanel (); // Create a content pane
content.setLayout (new BorderLayout ()); // Use BorderLayout for panel
JPanel north = new JPanel ();
north.setLayout (new FlowLayout ()); // Use FlowLayout for input area
DrawArea board = new DrawArea (500, 500);
// 3... Add the components to the input area.
content.add (north, "North"); // Input area
content.add (board, "South"); // Output area
// 4... Set this window's attributes.
setContentPane (content);
pack ();
setTitle ("MAZE");
setSize (490, 500);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo (null); // Center window.
}
public static void main (String[] args)
{
www window = new www ();
window.setVisible (true);
//jf.setTitle("Tutorial");
//jf.setSize(600,400);
}
class DrawArea extends JPanel
{
public DrawArea (int width, int height)
{
this.setPreferredSize (new Dimension (width, height)); // size
}
public void paintComponent (Graphics g)
{
maze.show (g); // display current state of colony
}
}
}
class Maze
{
private int grid [][];
public Maze ()
{
int [][] maze =
{ {1,0,1,1,1,1,1,1,1,1,1,1,1},
{1,0,1,0,1,0,1,0,0,0,0,0,1},
{1,0,1,0,0,0,1,0,1,1,1,0,1},
{1,0,0,0,1,1,1,0,0,0,0,0,1},
{1,0,1,0,0,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,0,0,1},
{1,0,1,0,1,0,0,0,1,1,1,0,1},
{1,0,1,0,1,1,1,0,1,0,1,0,1},
{1,0,0,0,0,0,0,0,0,0,1,0,1},
{1,1,1,1,1,1,1,1,1,1,1,0,1}};
grid = maze;
}
public void show (Graphics g)
{
for (int row = 0 ; row < grid.length ; row++)
for (int col = 0 ; col < grid [0].length ; col++)
{
if (grid [row] [col] == 1) // life
g.setColor (Color.black);
else
g.setColor (Color.white);
g.fillRect (col * 30 + 30, row * 30 + 30, 30, 30); // draw life form
}
g.setColor(Color.RED);
g.fillRect(60,30,30,50);
}
// public void player ()
// {
//
// Timer tm = new Timer(5,this);
// int x = 0;
// int y = 0;
// int velX = 0 ;
// int velY = 0;tm.start();
// addKeyListener(this);
// setFocusable(true);
// setFocusTraversalKeysEnabled(false);
// }
// public void actionPerformed(ActionEvent e)
// {
// x = x+velX;
// y = y +velY;
// repaint();
// }
// public void keyPressed(KeyEvent e)
// {
// int c = e.getKeyCode();
// if(c == KeyEvent.VK_LEFT)
// {
// velX = -1;
// velY = 0;
// }
// if (c == KeyEvent.VK_UP)
// {
// velX = 0;
// velY = -1;
// }
// if( c==KeyEvent.VK_RIGHT)
// {
// velX = 1;
// velY = 0;
// }
// if(c==KeyEvent.VK_DOWN)
// {
// velX = 0;
// velY = 1;
// }
// }
//
// public void keyTyped(KeyEvent e){}
//
// public void keyReleased(KeyEvent e){}
}
Your www class is a JFrame(extended) so you can add a keyListener to it like this:
First make a new class named MyKeyListener:
class MyKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent e)
{
int c = e.getKeyCode();
if(c == KeyEvent.VK_LEFT)
{
velX = -1;
velY = 0;
}
if (c == KeyEvent.VK_UP)
{
velX = 0;
velY = -1;
}
if( c==KeyEvent.VK_RIGHT)
{
velX = 1;
velY = 0;
}
if(c==KeyEvent.VK_DOWN)
{
velX = 0;
velY = 1;
}
}
}
(That's what you wrote which is correct)
Then do this in the initialization of your www class:
setKeyListener(new MyKeyListener());
This will add a key listener to the whole JFrame which will apply the keylistener to the whole grid.
EDIT: change the code to this:
public www ()
{
// 1... Create/initialize components
// 2... Create content pane, set layout
JPanel content = new JPanel (); // Create a content pane
content.setLayout (new BorderLayout ()); // Use BorderLayout for panel
JPanel north = new JPanel ();
north.setLayout (new FlowLayout ()); // Use FlowLayout for input area
DrawArea board = new DrawArea (500, 500);
// 3... Add the components to the input area.
content.add (north, "North"); // Input area
content.add (board, "South"); // Output area
// 4... Set this window's attributes.
setContentPane (content);
pack ();
setTitle ("MAZE");
setSize (490, 500);
setKeyListener(new MyKeylistener());
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo (null); // Center window.
}

Rotate a shape on the same axis in java

I have this program below. I want the program to rotate the shape on the same spot and also rotate the rectangle more than once. However, the program only rotates the rectangle once and puts the rotated shape on another spot on the frame. I really need help. Thanks!!!!*
import javax.swing.JPanel;
import java.awt.*;
import java.util.Random;
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.AffineTransform;
public class BoxesPanel extends JPanel
{
private boolean drawRect = false, drawCircle = false, Repaint = false;
private JButton enter;
int count = 0;
//------------------------------------------------------------------
// Sets up the drawing panel
//------------------------------------------------------------------
public BoxesPanel(int num)
{
if(num == 1)
drawRect = true;
else if(num == 2)
drawCircle = true;
enter = new JButton("click");
enter.addActionListener(new ButtonListener());
add(enter);
setBackground(Color.gray);
setPreferredSize(new Dimension(400, 400));
}
private class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
System.out.println("Rotate has been clicked: " + Repaint+ " " + count);
Repaint = true;
repaint();
}
}
public void paintComponent(Graphics page)
{
super.paintComponent(page);
Graphics2D g2d = (Graphics2D)page;
int x, y, width, height;
x = 100;
y = 100;
width = 100;
height = 100;
if(Repaint)
g2d.rotate(Math.toRadians(45), (x+width)/2, (y+height)/2);
g2d.setColor(Color.yellow);
AffineTransform old = g2d.getTransform();
if(drawRect)
g2d.fillRect(x,y,width,height);
else if(drawCircle)
g2d.fillOval(x,y,width,height);
g2d.setTransform(old);
System.out.println("Painted: " + Repaint+ " " + count);
Repaint = false;
}
}
import javax.swing.JFrame;
public class Boxes
{
//---------------------------------------------------------
// Creates the main frame of the program.
//---------------------------------------------------------
public static void main(String[] args)
{
JFrame frame = new JFrame ("Boxes");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BoxesPanel panel = new BoxesPanel(1);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
I made a few changes. It seems to work now.
public class BoxesPanel extends JPanel
{
private boolean drawRect = false, drawCircle = false;
private int angle = 0;
private JButton enter;
int count = 0;
//------------------------------------------------------------------
// Sets up the drawing panel
//------------------------------------------------------------------
public BoxesPanel(int num)
{
if(num == 1)
drawRect = true;
else if(num == 2)
drawCircle = true;
enter = new JButton("click");
enter.addActionListener(new ButtonListener());
add(enter);
setBackground(Color.gray);
setPreferredSize(new Dimension(400, 400));
}
private class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
System.out.println("Rotate has been clicked: " + count);
count++;
angle = (angle + 45)%360;
repaint();
}
}
public void paintComponent(Graphics page)
{
super.paintComponent(page);
Graphics2D g2d = (Graphics2D)page;
int x, y, width, height;
x = 100;
y = 100;
width = 100;
height = 100;
AffineTransform old = g2d.getTransform();
g2d.rotate(Math.toRadians(angle), x+width/2, y+height/2);
g2d.setColor(Color.yellow);
if(drawRect)
g2d.fillRect(x,y,width,height);
else if(drawCircle)
g2d.fillOval(x,y,width,height);
g2d.setTransform(old);
System.out.println("Painted: " + count);
}
}

Java - Circles with lines connecting the centers

I have a JFrame with a subclass, Paint_Panel. Paint_Panel extends JPanel and implements a MouseListener.
I need to place three circles with mouse clicks. No problem. I have a button (Draw) that should draw lines from each circle's center to the other (thus - a triangle). I can maintain the coordinates within an ArrayList - no problem. However, when I try to reference the ArrayList by clicking the button, the list is returned empty. The Array isn't in memory at the time it is needed to draw the lines. Thoughts?
Note- Circles are hard-coded at 40.
Code:
public class Paint_Panel extends JPanel implements MouseListener {
public static int flag = 0;
boolean drawCircles = false;
boolean drawLines = false;
private final ArrayList<Point> points = new ArrayList<>();
public Paint_Panel() {
addMouseListener(this);
}
//Method to draw lines from point to point
public void drawLines() {
Graphics g = getGraphics();
drawLines = true;
paintComponent(g);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (drawCircles) {
for (int i = 0; i < points.size(); i++) {
//Circle number 1
g.setColor(Color.RED);
g.fillOval(points.get(0).x - 20, points.get(0).y - 20, 40, 40);
//Circle number 2
if (points.size() >= 2) {
g.setColor(Color.GREEN);
g.fillOval(points.get(1).x - 20, points.get(1).y - 20, 40, 40);
}
//Circle number 3
if (points.size() >= 3) {
g.setColor(Color.BLUE);
g.fillOval(points.get(2).x - 20, points.get(2).y - 20, 40, 40);
}
}
} else if (drawLines) {
g.setColor(Color.BLACK); //Set line color
g.drawLine(points.get(0).x, points.get(0).y, points.get(1).x, points.get(1).y);
g.drawLine(points.get(1).x, points.get(1).y, points.get(2).x, points.get(2).y);
g.drawLine(points.get(2).x, points.get(2).y, points.get(0).x, points.get(0).y);
}
}
public void mouseClicked(MouseEvent evt) { //Place circles for click event
Graphics g = getGraphics();
if (!drawCircles) {
prevX = evt.getX() - 20; //Allows placement at center. Size - radius
prevY = evt.getY() - 20;
points.add(evt.getPoint()); //Add point to ArrayList
if (flag < 3) { //Keep track of how many circles are placed
flag += 1;
drawCircles = true;
paintComponent(g);
} else if (flag == 3) { //If additional circles attempted, inform user
flag = 4;
System.out.println("Only 3 circles allowed."); //Debug
drawCircles = false;
}
}
drawCircles = false;
}
#Override
public void mousePressed(MouseEvent evt) { //Unused
}
#Override
public void mouseReleased(MouseEvent evt) { //Unused
}
#Override
public void mouseEntered(MouseEvent evt) { //Unused
}
#Override
public void mouseExited(MouseEvent evt) { //Unused
}
}
Here's one way to draw 3 circles and 3 lines. Edited to draw the circles first, then the lines. Edited again to check for an invalid button press.
I separated the view and controller logic.
Here's the runnable code.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CirclePaintTest implements Runnable {
private JFrame frame;
private PaintPanel paintPanel;
#Override
public void run() {
frame = new JFrame("Circle Paint Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
paintPanel = new PaintPanel();
mainPanel.add(paintPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
JButton lineButton = new JButton("Draw Lines");
lineButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (paintPanel.isComplete()) {
paintPanel.setDrawLines(true);
paintPanel.repaint();
}
}
});
buttonPanel.add(lineButton);
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new CirclePaintTest());
}
public class PaintPanel extends JPanel {
private static final long serialVersionUID = 6481890334304291711L;
private final Color[] colors = { Color.RED, Color.GREEN, Color.BLUE,
Color.ORANGE, Color.CYAN, Color.YELLOW };
private boolean drawLines;
private final int pointLimit;
private final List<Point> points;
public PaintPanel() {
this.points = new ArrayList<Point>();
this.pointLimit = 3;
this.drawLines = false;
this.addMouseListener(new CircleMouseListener());
this.setPreferredSize(new Dimension(400, 400));
}
public void setDrawLines(boolean drawLines) {
this.drawLines = drawLines;
}
public boolean isComplete() {
return points.size() >= pointLimit;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Point pp = null;
Point p0 = null;
for (int i = 0; i < points.size(); i++) {
g.setColor(colors[i]);
Point p = points.get(i);
g.fillOval(p.x - 20, p.y - 20, 40, 40);
pp = p;
}
if (drawLines && (points.size() > 1)) {
p0 = points.get(0);
pp = p0;
g.setColor(Color.BLACK);
for (int i = 1; i < points.size(); i++) {
Point p = points.get(i);
g.drawLine(pp.x, pp.y, p.x, p.y);
pp = p;
}
g.drawLine(pp.x, pp.y, p0.x, p0.y);
}
}
public class CircleMouseListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent event) {
if (points.size() < pointLimit) {
points.add(event.getPoint());
PaintPanel.this.repaint();
}
}
}
}
}
You don't call repaint when flag equals 3, so there is no call to the paintComponent method with the right condition (drawCircles false and drawLines true).
I suggest you to call repaint either when flag equals to 3 or and the end of mouseClicked.

dragging a jlabel around the screen

So I am trying to click and drag a JLabel around a JFrame. The following code allows a JLabel to be moved around the screen when the mouse is pressed / dragged at any point on the screen, but I am not sure how to add a second ActionListener to check if the mouse is clicking on the label, assuming that is the solution.
I would like to have multiple JLabels on the screen so that the only label being moved is the one that the mouse has clicked and is now dragging.
Thanks.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class test extends JFrame implements MouseMotionListener {
private JPanel panel = new JPanel(null);
private JLabel dragLabel = new JLabel("drag test");
private int mouseX = 200;
private int mouseY = 200;
public test() {
this.add(panel);
panel.setBackground(Color.WHITE);
panel.add(dragLabel);
dragLabel.setForeground(Color.RED);
dragLabel.setBounds(mouseX, mouseY, 100, 50);
panel.addMouseMotionListener(this);
}
#Override
public void mouseDragged(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
dragLabel.setBounds(mouseX, mouseY, 100, 50);
}
#Override
public void mouseMoved(MouseEvent e) {}
public static void main(String[] args) {
test frame = new test();
frame.setVisible(true);
frame.setSize(600, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Another way to do this is to add the JLabel to a JLayeredPane or to a JPanel held by a JLayeredPane and add a MouseAdapter as the JLayeredPane's MouseListener and MouseMotionListener. Then when clicking on the label, move it to the JLayeredPane's JLayeredPane.DRAG_LAYER so it moves on top of everything else, then place the JLabel on whichever is the most appropriate level on mouse release. I've found this to work well when moving chess pieces on a chess board, for instance, and you want to make sure that the piece you're moving is displayed above all the other pieces when dragging.
Addition: You've probably left this thread, but if you come back, or for the benefit of others, I wanted to clarify what I meant by using a JLayeredPane by posting an example.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragLabelOnLayeredPane extends JLayeredPane {
public static final int WIDTH = 680;
public static final int HEIGHT = 480;
private static final int GRID_ROWS = 8;
private static final int GRID_COLS = 6;
private static final int GAP = 3;
private static final Dimension LAYERED_PANE_SIZE = new Dimension(WIDTH, HEIGHT);
private static final Dimension LABEL_SIZE = new Dimension(60, 40);
private GridLayout gridlayout = new GridLayout(GRID_ROWS, GRID_COLS, GAP, GAP);
private JPanel backingPanel = new JPanel(gridlayout);
private JPanel[][] panelGrid = new JPanel[GRID_ROWS][GRID_COLS];
private JLabel redLabel = new JLabel("Red", SwingConstants.CENTER);
private JLabel blueLabel = new JLabel("Blue", SwingConstants.CENTER);
public DragLabelOnLayeredPane() {
backingPanel.setSize(LAYERED_PANE_SIZE);
backingPanel.setLocation(2 * GAP, 2 * GAP);
backingPanel.setBackground(Color.black);
for (int row = 0; row < GRID_ROWS; row++) {
for (int col = 0; col < GRID_COLS; col++) {
panelGrid[row][col] = new JPanel(new GridBagLayout());
backingPanel.add(panelGrid[row][col]);
}
}
redLabel.setOpaque(true);
redLabel.setBackground(Color.red.brighter().brighter());
redLabel.setPreferredSize(LABEL_SIZE);
panelGrid[4][3].add(redLabel);
blueLabel.setOpaque(true);
blueLabel.setBackground(Color.blue.brighter().brighter());
blueLabel.setPreferredSize(LABEL_SIZE);
panelGrid[1][1].add(blueLabel);
backingPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setPreferredSize(LAYERED_PANE_SIZE);
add(backingPanel, JLayeredPane.DEFAULT_LAYER);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
private class MyMouseAdapter extends MouseAdapter {
private JLabel dragLabel = null;
private int dragLabelWidthDiv2;
private int dragLabelHeightDiv2;
private JPanel clickedPanel = null;
#Override
public void mousePressed(MouseEvent me) {
clickedPanel = (JPanel) backingPanel.getComponentAt(me.getPoint());
Component[] components = clickedPanel.getComponents();
if (components.length == 0) {
return;
}
// if we click on jpanel that holds a jlabel
if (components[0] instanceof JLabel) {
// remove label from panel
dragLabel = (JLabel) components[0];
clickedPanel.remove(dragLabel);
clickedPanel.revalidate();
clickedPanel.repaint();
dragLabelWidthDiv2 = dragLabel.getWidth() / 2;
dragLabelHeightDiv2 = dragLabel.getHeight() / 2;
int x = me.getPoint().x - dragLabelWidthDiv2;
int y = me.getPoint().y - dragLabelHeightDiv2;
dragLabel.setLocation(x, y);
add(dragLabel, JLayeredPane.DRAG_LAYER);
repaint();
}
}
#Override
public void mouseDragged(MouseEvent me) {
if (dragLabel == null) {
return;
}
int x = me.getPoint().x - dragLabelWidthDiv2;
int y = me.getPoint().y - dragLabelHeightDiv2;
dragLabel.setLocation(x, y);
repaint();
}
#Override
public void mouseReleased(MouseEvent me) {
if (dragLabel == null) {
return;
}
remove(dragLabel); // remove dragLabel for drag layer of JLayeredPane
JPanel droppedPanel = (JPanel) backingPanel.getComponentAt(me.getPoint());
if (droppedPanel == null) {
// if off the grid, return label to home
clickedPanel.add(dragLabel);
clickedPanel.revalidate();
} else {
int r = -1;
int c = -1;
searchPanelGrid: for (int row = 0; row < panelGrid.length; row++) {
for (int col = 0; col < panelGrid[row].length; col++) {
if (panelGrid[row][col] == droppedPanel) {
r = row;
c = col;
break searchPanelGrid;
}
}
}
if (r == -1 || c == -1) {
// if off the grid, return label to home
clickedPanel.add(dragLabel);
clickedPanel.revalidate();
} else {
droppedPanel.add(dragLabel);
droppedPanel.revalidate();
}
}
repaint();
dragLabel = null;
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("DragLabelOnLayeredPane");
frame.getContentPane().add(new DragLabelOnLayeredPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Please feel free to post any questions, need for clarification, or corrections.
Inspired by your code and user compilex's answer, follows demonstration:
Full code:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
/**
* A demonstration of moving around labels in a panel.
* <p>
* Some labels show up layed out in a grid. Then the
* user can drag any label anywhere on the panel.
* </p>
*/
public class LabelDragger {
public static void main(final String[] args) {
final int labelRows = 5, //How many rows of labels.
labelColumns = 5, //How many columns of labels.
labelWidth = 55, //Width for each label.
labelHeight = 20; //Height for each label.
//Border colors for labels:
final Color[] colors = new Color[]{Color.BLUE, Color.GREEN, Color.BLACK, Color.GRAY};
final Random prng = new Random(); //For selecting border color for each label.
final JPanel dragP = new JPanel(null); //Nicely set to null! :D Did not know that trick.
//Creating the listener for the panel:
final MouseAdapter ma = new MouseAdapter() {
private JLabel selectedLabel = null; //Clicked label.
private Point selectedLabelLocation = null; //Location of label in panel when it was clicked.
private Point panelClickPoint = null; //Panel's click point.
//Selection of label occurs upon pressing on the panel:
#Override
public void mousePressed(final MouseEvent e) {
//Find which label is at the press point:
final Component pressedComp = dragP.findComponentAt(e.getX(), e.getY());
//If a label is pressed, store it as selected:
if (pressedComp != null && pressedComp instanceof JLabel) {
selectedLabel = (JLabel) pressedComp;
selectedLabelLocation = selectedLabel.getLocation();
panelClickPoint = e.getPoint();
//Added the following 2 lines in order to make selectedLabel
//paint over all others while it is pressed and dragged:
dragP.setComponentZOrder(selectedLabel, 0);
selectedLabel.repaint();
}
else {
selectedLabel = null;
selectedLabelLocation = null;
panelClickPoint = null;
}
}
//Moving of selected label occurs upon dragging in the panel:
#Override
public void mouseDragged(final MouseEvent e) {
if (selectedLabel != null
&& selectedLabelLocation != null
&& panelClickPoint != null) {
final Point newPanelClickPoint = e.getPoint();
//The new location is the press-location plus the length of the drag for each axis:
final int newX = selectedLabelLocation.x + (newPanelClickPoint.x - panelClickPoint.x),
newY = selectedLabelLocation.y + (newPanelClickPoint.y - panelClickPoint.y);
selectedLabel.setLocation(newX, newY);
}
}
};
dragP.addMouseMotionListener(ma); //For mouseDragged().
dragP.addMouseListener(ma); //For mousePressed().
//Filling the panel with labels:
for (int row = 0; row < labelRows; ++row)
for (int col = 0; col < labelColumns; ++col) {
//Create label for (row, col):
final JLabel lbl = new JLabel("Label" + (row * labelColumns + col));
lbl.setHorizontalAlignment(JLabel.CENTER);
//lbl.setVerticalAlignment(JLabel.CENTER);
lbl.setBounds(col * labelWidth, row * labelHeight, labelWidth, labelHeight); //Grid-like positioning.
lbl.setBorder(new LineBorder(colors[prng.nextInt(colors.length)], 2)); //Set a border for clarity.
//Add label to panel:
dragP.add(lbl);
}
//Creating and showing the main frame:
final JFrame frame = new JFrame(LabelDragger.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//The size of the content pane adds some extra room for moving the labels:
final Dimension paneSize = new Dimension((int)(1.5 * labelWidth * labelColumns),
(int)(1.5 * labelHeight * labelRows));
frame.getContentPane().setPreferredSize(paneSize);
frame.getContentPane().add(dragP);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Explanations are added as comments.
Tips:
Take a look at the documentation on Container.findComponentAt(int x, int y), if you are going to add Components on the dragP Container, other than "draggable" labels.
Also, you can instead use Container.getComponentAt(int x, int y), in this case. I suggest you read their (small) documentation first.
Add a mouse listener to the label instead of the panel. (You might still need a mouse listener on the panel for the dragging but at least the one on the label can tell you if it was selected).
Create two global variables:
int x_pressed = 0;
int y_pressed = 0;
then create two events (mousePressed and mouseDragged over JLabel):
lbl_banner.addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e) {
//catching the current values for x,y coordinates on screen
x_pressed = e.getX();
y_pressed = e.getY();
}
});
lbl_banner.addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent e){
//and when the Jlabel is dragged
setLocation(e.getXOnScreen() - x_pressed, e.getYOnScreen() - y_pressed);
}
});

Categories