fornit fornit - 3 months ago 40
Java Question

Create a clickable area around round JLabel image

I am trying to create a JLabel with a oval shaped image, like this.

enter image description here

My code is the following:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public final class RoundedButtonDemo {
private static Image bi;

public static void main(String[] args) {
try {
loadImage();

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
} catch (IOException e) {
// handle exception
}
}

private static void loadImage() throws IOException {
int newWidth = 80;
int newHeight = 40;
bi = ImageIO.read(RoundedButtonDemo.class.getResource("/resources/login.png"));
bi = bi.getScaledInstance(newWidth, newHeight, Image.SCALE_DEFAULT);

}

private static void createAndShowGUI() {
final JFrame frame = new JFrame();
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

final JLabel label = new JLabel();
label.setSize(new Dimension(5, 5));
label.setIcon(new ImageIcon(bi));
label.setText("Hello World");
label.setHorizontalTextPosition(JLabel.CENTER);
// label.setBorder(BorderFactory.createLineBorder(Color.BLACK));

label.addMouseListener(new MouseListener() {

private int count = 0;

@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() == label) {
if (count % 2 == 0) {
label.setText("Bye");
} else {
label.setText("Hello World");
}

count++;
}
}

@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub

}

@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub

}

@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub

}
});

frame.add(label);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}


This code creates a
JLabel
containing the above image. The text of the
JLabel
should alternate every time the button is clicked, based on a
MouseListener
added to the
JLabel
.

The problem I'm facing is that even when I click outside the image (also outside the
JLabel
), the
MouseListener
is triggered, and the text alternates.

The big picture of what I want to achieve is :
A rounded button which responds to a
MouseListener
, whenever it is clicked anywhere on its surface.

Answer

I tried your code. You are getting this behavior because your JLabel is actually filling the entire frame. You need to set a layout for your frame; something like this:

// ...
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());             // <-- you need this

final JLabel label = new JLabel();
label.setPreferredSize(new Dimension(80, 40)); // <-- also this
label.setIcon(new ImageIcon(bi));
label.setText("Hello World");
// ...

FlowLayout is one of the simplest layout managers, of which there are many. You can read about them here: https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html

Hope this helps.

PS: you had a good idea trying to debug this problem, adding a border like this:

// label.setBorder(BorderFactory.createLineBorder(Color.BLACK));

Not sure why you commented it out. Maybe you didn't notice that there was a black border around the whole frame area. Try setting to color to Color.RED or something more noticeable.