Java how to move a paint componenet [duplicate] - java

I'm trying to move the boat on the x-axis (without the keyboard yet). How can I relate the movement/ animation to the boat.png and not to any other image?
public class Mama extends Applet implements Runnable {
int width, height;
int x = 200;
int y = 200;
int dx = 1;
Image img1, img2, img3, img4;
#Override
public void init(){
setSize(627, 373);
Thread t = new Thread(this);
img1 = getImage(getCodeBase(),"Background.png");
img2 = getImage(getCodeBase(), "boat.png");
img3 = getImage(getCodeBase(), "LeftPalm.png");
img4 = getImage(getCodeBase(), "RightPalm.png");
}
#Override
public void paint(Graphics g){
g.drawImage(img1, 0, 0, this);
g.drawImage(img2, 200, 200, this);
g.drawImage(img3, 40, 100, this);
g.drawImage(img4, 450, 130, this);
}
#Override
public void run() {
while(true){
x += dx;
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
System.out.println("Thread generates an error.");
}
}
}
}

There are a few things that stand out...
The "Problem"
As has already been stated, you need to supply variable arguments to the image drawing process. g.drawImage(img2, x, y, this);, this will allow you define where the image should be painted.
While you've implemented Runnable, you've actually not started any threads to call it. This means, nothing is actually changing the variables.
In you start method, you should be calling something like new Thread(this).start().
Recommendations
Although you've tagged the question as Swing, you're using AWT components. This isn't recommended (in fact applets are generally discouraged as they are troublesome - IMHO). The other problem, as you are bound to find out shortly, is they are not double buffered, this generally leads to flickering when performing animation, which isn't desirable.
As a side note, it is also discouraged to override the paint method of top level containers like Applet. Top level containers tend to contain a number additional components, by overriding the paint method like this, you destroy this setup. Also, top level containers don't tend to be double buffered either.
The example below uses a JFrame, but it wouldn't take much to convert it to use a JApplet (just drop the AnimationPanel on to it. This is another reason why extending from top level containers is generally discouraged ;)
public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}

You need to replace g.drawImage(img2, 200, 200, this); with g.drawImage(img2, x, y, this);

Related

How to make an image move from left to right in Java

so far i have created the class below, however, now i would like to insert a code to make the image slide from left to right and right to left. I would normally use the Sliding platform however it doesn't work when i try to implement it. I am still a beginner in java so i am grateful for your help.
This is the code of my Java Class:
package game;
import city.soi.platform.*;
public class Enemy extends Body implements CollisionListener{
private Game game ;
public Enemy(Game g){
super(g.getWorld(), new PolygonShape(-27.0f,25.0f, -27.0f,-24.0f, 25.0f,-24.0f, 26.0f,25.0f, -27.0f,25.0f));
setImage(new BodyImage("images/enemy.png"));
g.getWorld().addCollisionListener(this);
game = g;
}
public void collide(CollisionEvent e) {
if (e.getOtherBody() == game.getPlayer()){
game.getPlayer().subtractFromScore(75);
System.out.println("You have just lossed 75 Points! Current Score = " + game.getPlayer().getScore());
this.destroy();
}
}
}
Just to be clear i would like everyone i include this class onto a platform it moves from left to right.
Many Thanks,
Moe
This will depend a lot on what you individual requirements, but the basic concepts will remain the same.
Any type of animation in Swing must be executed in such away that it does not block the Event Dispatching Thread. Any blocking action on the EDT will prevent any repaint request (amongst other things) from been processed.
This simple example uses a javax.swing.Timer that ticks every 40 milliseconds or so (about 25 fps) and updates the position of a small "ball"
More complex iterations would require a dedicated Thread. This makes the whole process far more complex as
You should never update/create/modify/change any UI component (or property that the UI may require to perform painting) from any thread other then the EDT
You don't control the paint process. This means a repaint may occur at anytime and if you are modifying any property/object that the paint process requires to render the state of the game, it could cause inconsistencies.
.
public class SimpleBouncyBall {
public static void main(String[] args) {
new SimpleBouncyBall();
}
public SimpleBouncyBall() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CourtPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CourtPane extends JPanel {
private Ball ball;
private int speed = 5;
public CourtPane() {
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Rectangle bounds = new Rectangle(new Point(0, 0), getSize());
if (ball == null) {
ball = new Ball(bounds);
}
speed = ball.move(speed, bounds);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (ball != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Point p = ball.getPoint();
g2d.translate(p.x, p.y);
ball.paint(g2d);
g2d.dispose();
}
}
}
public class Ball {
private Point p;
private int radius = 12;
public Ball(Rectangle bounds) {
p = new Point();
p.x = 0;
p.y = bounds.y + (bounds.height - radius) / 2;
}
public Point getPoint() {
return p;
}
public int move(int speed, Rectangle bounds) {
p.x += speed;
if (p.x + radius >= (bounds.x + bounds.width)) {
speed *= -1;
p.x = ((bounds.x + bounds.width) - radius) + speed;
} else if (p.x <= bounds.x) {
speed *= -1;
p.x = bounds.x + speed;
}
p.y = bounds.y + (bounds.height - radius) / 2;
return speed;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
g.fillOval(0, 0, radius, radius);
}
}
}

How to move an image (animation)?

I'm trying to move the boat on the x-axis (without the keyboard yet). How can I relate the movement/ animation to the boat.png and not to any other image?
public class Mama extends Applet implements Runnable {
int width, height;
int x = 200;
int y = 200;
int dx = 1;
Image img1, img2, img3, img4;
#Override
public void init(){
setSize(627, 373);
Thread t = new Thread(this);
img1 = getImage(getCodeBase(),"Background.png");
img2 = getImage(getCodeBase(), "boat.png");
img3 = getImage(getCodeBase(), "LeftPalm.png");
img4 = getImage(getCodeBase(), "RightPalm.png");
}
#Override
public void paint(Graphics g){
g.drawImage(img1, 0, 0, this);
g.drawImage(img2, 200, 200, this);
g.drawImage(img3, 40, 100, this);
g.drawImage(img4, 450, 130, this);
}
#Override
public void run() {
while(true){
x += dx;
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
System.out.println("Thread generates an error.");
}
}
}
}
There are a few things that stand out...
The "Problem"
As has already been stated, you need to supply variable arguments to the image drawing process. g.drawImage(img2, x, y, this);, this will allow you define where the image should be painted.
While you've implemented Runnable, you've actually not started any threads to call it. This means, nothing is actually changing the variables.
In you start method, you should be calling something like new Thread(this).start().
Recommendations
Although you've tagged the question as Swing, you're using AWT components. This isn't recommended (in fact applets are generally discouraged as they are troublesome - IMHO). The other problem, as you are bound to find out shortly, is they are not double buffered, this generally leads to flickering when performing animation, which isn't desirable.
As a side note, it is also discouraged to override the paint method of top level containers like Applet. Top level containers tend to contain a number additional components, by overriding the paint method like this, you destroy this setup. Also, top level containers don't tend to be double buffered either.
The example below uses a JFrame, but it wouldn't take much to convert it to use a JApplet (just drop the AnimationPanel on to it. This is another reason why extending from top level containers is generally discouraged ;)
public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}
You need to replace g.drawImage(img2, 200, 200, this); with g.drawImage(img2, x, y, this);

Fast switching between two images?

I want to make an object to open mouth and close it using two images that switch quickly. I tried with a for loop but it lagged my game.
if(direction == Constant.UP){
ImageIcon i = new ImageIcon("src\\images\\pacman up.png");
image = i.getImage();
ImageIcon i2 = new ImageIcon("src\\images\\pacman left.png");
image = i2.getImage();
}
G.drawImage(image, x, y, 20,20,null);
Any animation in Swing needs to take into consideration the Event Dispatching Thread.
You should NEVER perform any action within the content of the EDT that may block it (such as loops or I/O) as this will prevent the EDT from (amongst other things) processing paint requests.
You should always use a surface capable of supporting double buffer, such as JPanel as this will help eliminate flickering
The following uses a javax.swing.Timer to switch between the two images...
public class TestPacMan {
public static void main(String[] args) {
new TestPacMan();
}
public TestPacMan() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PacManPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PacManPane extends JPanel {
private BufferedImage pacOpened;
private BufferedImage pacClosed;
private BufferedImage frame;
private boolean opened = true;
public PacManPane() {
try {
pacOpened = ImageIO.read(new File("PC-Closed.png"));
pacClosed = ImageIO.read(new File("PC-Opened.png"));
frame = pacOpened;
} catch (IOException exp) {
exp.printStackTrace();
}
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
opened = !opened;
frame = opened ? pacOpened : pacClosed;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (frame != null) {
int x = (getWidth() - frame.getWidth()) / 2;
int y = (getHeight() - frame.getHeight()) / 2;
g2d.drawImage(frame, x, y, this);
}
g2d.dispose();
}
}
}
don't create the icon each time. create the two images at startup and just switch back
and forth at runtime.
if(direction == Constant.UP){
image = open;
}else {
image = closed;
}
G.drawImage(image, x, y, 20,20,null);

Java applet only partially paints

I'm new to Java applet programming, so excuse me if this is a very basic question, but I've googled it extensively and have only found semi-related problems and solutions.
I'm writing a simple demonstration of some geometric algorithms, and when I repaint(), only some of my graphics primitives are rendered to the screen. Every time my applet redraws, a seemingly random subset of my lines and ellipses are painted. The only pattern to it is that the primitives that are rendered are always from the beginning of the drawing. I.E, sometimes it will draw primitives 0-2, sometimes 0-5, sometimes the whole batch.
I would like to point out that, as far as I can tell, this is not the classic "flickering" that can be solved with double-bufferring. To my understanding, flickering is when for short periods of time you can see a partially rendered applet before it finishes rendering. In my case, however, if it doesn't finish rendering, it never finishes unless I redraw() again and get lucky. I've tried double buffering:
public void update(Graphics g) {
Graphics offgc;
Image offscreen = null;
Dimension d = size();
// create the offscreen buffer and associated Graphics
offscreen = createImage(d.width, d.height);
offgc = offscreen.getGraphics();
// clear the exposed area
offgc.setColor(getBackground());
offgc.fillRect(0, 0, d.width, d.height);
offgc.setColor(getForeground());
// do normal redraw
paint(offgc);
// transfer offscreen to window
g.drawImage(offscreen, 0, 0, this);
}
But it doesn't seem to help at all. If it's useful, here's some pics of what's happening. This is what it's supposed to look like:
But most of the time it looks something like this:
or this:
Thanks in advance!
This isn't really how double buffering should work, no is it how the paint process works.
Don't override update.
Don't override paint of top level containers (like Applet/JApplet/Frame/JFrame) where possible
Use a "paint" panel onto which you can render, preferably something like JPanel. Swing components provide double buffering support
A double buffer should be painted on out side the paint cycle and only updated when needed, this makes the overall paint process faster as you're not having re-render the content unnecessarily.
When it comes time to update the buffer, render to a temp buffer first, this ensures that any repaints that might occur while you're updating aren't reflected back to the screen prematurely...
public class TestPaintGeometry {
public static void main(String[] args) {
new TestPaintGeometry();
}
public TestPaintGeometry() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ShowPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ShowPane extends JPanel {
private GeometryPane geoPane;
public ShowPane() {
setLayout(new BorderLayout());
geoPane = new GeometryPane();
JButton redrew = new JButton("Redraw");
add(geoPane);
add(redrew, BorderLayout.SOUTH);
redrew.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
geoPane.redrew();
}
});
}
}
public class GeometryPane extends JPanel {
private BufferedImage buffer;
public void redrew() {
Path2D.Float path = new Path2D.Float();
int width = getWidth();
int height = getHeight();
int points = Math.max(10, (int) Math.round(Math.random() * 100));
for (int index = 0; index < points; index++) {
int x = (int) Math.round(Math.random() * width);
int y = (int) Math.round(Math.random() * height);
if (index > 0) {
path.lineTo(x, y);
} else {
path.moveTo(x, y);
}
}
BufferedImage tmp = createCompatibleImage(width, height);
Graphics2D g2d = tmp.createGraphics();
g2d.setColor(Color.BLACK);
g2d.draw(path);
g2d.dispose();
buffer = tmp;
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (buffer != null) {
int x = (getWidth() - buffer.getWidth()) / 2;
int y = (getHeight() - buffer.getHeight()) / 2;
g.drawImage(buffer, x, y, this);
}
}
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
public static BufferedImage createCompatibleImage(int width, int height) {
return createCompatibleImage(width, height, Transparency.TRANSLUCENT);
}
public static BufferedImage createCompatibleImage(int width, int height, int transparency) {
BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
}
This allows you deploy the GeometryPane to a JFrame or JAppelt as it's not constrained by the legacy of it's inheritance...

JLabel Overlapping

I have created a label with overriding its paintComponent (to paint it in a different format with an arc) and located them on a panel. Everything worked fine, however the labels which are located in same location (by .setlocation) are creating problems.
Lets say I have 3 labels at the same location with different shapes. A-B-C
A is first created, then B is created and lastly c is created.
When I click on A, my function paints A and displays "youve clicked A"
But when I click on B or C, it acts like i have clicked on A.
(I'm adding labels in a panel stacked in scroll pane )
Here is the code where i make labels
for(int i=0;i<rowcount;i++){
arcstart = Rawazimuth(azimuth[i]);
//custom JLabel to paint it like an arc
MyLabel FLabel = new MyLabel(100, 50, (int)arcstart,cellid[i],lon[i],lat[i]);
FLabel.setOpaque(true);
Dimension LabelSize = new Dimension( 100,50);
FLabel.setSize(LabelSize);
//locate the JLabel to labels location. it might be same or not
FLabel.setLocation(lon[i], lat[i]);
MyPanel.add(FLabel);
}
this is my custom jlabel class
public MyLabel(int W, int H, int start,int outcellid,int lonn, int latt) {
addMouseListener(this);
arcsizeW = W;
arcsizeH = H;
arcstart = start;
cellid = outcellid;
clicked = false;
lon = lonn;
lat = latt;
}
#Override
public void paintComponent(Graphics g){
// true if button is clicked, so paint acordingly
if(clicked ==true){
g.setColor(dummyg.getColor());
}else{
g.setColor(Color.blue);
}
// draw the arc
g.fillArc(0, 0,arcsizeW , arcsizeH, arcstart, 60);
}
//if cell is clicked, change its color to red and print its cellid
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(cellid);
dummyg = this.getGraphics();
dummyg.setColor(Color.red);
this.paintComponent(dummyg);
clicked = true;
}// other listener stuff}
so how do i prevent this?
i think i can use jlayerpane, but i will need at least 4 layers ( dunno if its ok ).
Make sure you are calling super.paintComponent. This is important to ensure that the component is painting correcting.
Mouse events are like rain. They will hit the first component registered to receive mouse events and stop (like rain hitting an umbrella).
If you have components that overlap, where they overlap, the mouse events go to the first component registered to handle them (in this case A).
Here's a quick example to show what I mean...
As you hover over each circle, it will highlight, try hovering over the middle...
public class OverlappingMouseTest {
public static void main(String[] args) {
new OverlappingMouseTest();
}
public OverlappingMouseTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BackgroundPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class BackgroundPane extends JLayeredPane {
private CirclePane redPane;
private CirclePane greenPane;
private CirclePane bluePane;
public BackgroundPane() {
redPane = new CirclePane(Color.RED);
greenPane = new CirclePane(Color.GREEN);
bluePane = new CirclePane(Color.BLUE);
add(redPane);
add(greenPane);
add(bluePane);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void doLayout() {
Dimension size = new Dimension(100, 100);
int width = getWidth() - 1;
int height = getHeight() - 1;
Point p = new Point();
p.x = (width / 2) - 50;
p.y = (height / 2) - 75;
redPane.setBounds(new Rectangle(p, size));
p.x = (width / 2) - 75;
p.y = (height / 2) - 25;
bluePane.setBounds(new Rectangle(p, size));
p.x = (width / 2) - 25;
p.y = (height / 2) - 25;
greenPane.setBounds(new Rectangle(p, size));
}
}
protected class CirclePane extends JPanel {
private boolean mouseHover = false;
public CirclePane(Color background) {
setOpaque(false);
setBackground(background);
addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent me) {
mouseHover = false;
repaint();
}
#Override
public void mouseEntered(MouseEvent me) {
mouseHover = true;
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
Graphics2D g2d = (Graphics2D) grphcs.create();
if (!mouseHover) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
}
g2d.setColor(getBackground());
g2d.fill(new Ellipse2D.Float(0, 0, getWidth() - 1, getHeight() - 1));
g2d.dispose();
}
}
}
Everything worked fine, however the JLabel's which are located in same
location ( by .setlocation ) are creating problems.
Lets say i have 3 Jlabels at the same location with different shapes.
A-B-C A is first created, then B is created and lastly c is created.
there are tree ways, to use
JLayer (Java7), based on JXLayer (Java6)
OverlayLayout
JLayeredPane
I have solved my problem.
The real problem that i found was, Java is interpreting each component with their x,y location and width & height. So even if your label does not overlap ( graphically ) they can be interpreted as same component.
To solve my problem,
I found the angle between mouse click point and component center; then calculated the closest component and reached it.
Layers and such doesn't work in this situation, the only other way around is possibly overriding the contains method for the actualy shape.

Categories