4

I have a custom component displaying *.png image. The image has transparent and non-transparent area. If I add ActionListener(or MouseClickListener) to component, it will raise events even if I click on transparent area of component. Visually it looks like clicking outside the component. How can I declare which area should react on clicks and which should not?

I've read about getting pixel from image your coordinates from event object and check its transparency. It seems difficult and ineffective.

Maybe define custom-border of this component or something else?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Yegoshin Maxim
  • 872
  • 2
  • 21
  • 54
  • 3
    You could try to add a check inside your listener to verify if the coordinates of the mouse click came from a non-transparent area – Alex Jan 18 '12 at 14:35
  • I wrote about that case. It complex enough. If I going to check it in mouseEnter() handler than I should check EVERY mouse position point. And for every mouse position point I have to get that pixel from image and check transparency. There's much overhead. – Yegoshin Maxim Jan 18 '12 at 14:42
  • 1
    "There's much overhead", indeed, but either Java does it automatically, for all images, or you do it for this one specific case where it matters to you. That second one makes more sense! – Ernest Friedman-Hill Jan 18 '12 at 14:50
  • [Fully covered here][1] [1]: http://stackoverflow.com/questions/6735891/creating-custom-jbutton-from-images-containing-transparent-pixels The question may be closed. – Yegoshin Maxim Jan 18 '12 at 17:18

4 Answers4

3

You answered your own question.

Within the mousePressed() event handler, you're going to have to check if you're within the JComponent, and then check the pixel at the x and y coordinate of the mouse click for transparency.

Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
  • I've wrote about overhead. For example I'm going to make 70% opacity if mouse leaves area and 100% opacity when mouse enters the area. I have to do too much checks. Is this the only way? – Yegoshin Maxim Jan 18 '12 at 14:58
  • 1
    @Yegoshin Maxim: First, make your code work. Then, when you can measure the execution, make your code efficient. You can produce the 70% image from the 100% image once, and swap the images on mouseEnter and mouseLeave. – Gilbert Le Blanc Jan 18 '12 at 15:01
  • May be I'm wrong but it seems to me than ImageView in javaFX raises mouseEntered() only if your enter a non-transparent area. Does similar class exist in Swing ? – Yegoshin Maxim Jan 18 '12 at 15:34
2

How can I declare which area should react on clicks and which should not?

This is done at the JComponent level by overriding the contains(...) method. So for example you extend JLabel to create a TransparentLabel which contain your image in the form of an icon.

Then whenever this method is invoked you only need to check this one location to determine if the pixel is transparent or not.

camickr
  • 321,443
  • 19
  • 166
  • 288
1

If your main issue about "overhead" is that you only want to make it opaque when the mouse enters a non-transparent part of the image, I'd consider pre-computing an image "mask".

On image load, make another image (or a 2d array, or something similar) that will be binary (i.e. black-and-white only, or 1 and 0 values only in an array). 0/white = transparent, 1/black = non-transparent.

Then, on mouse events, you can just check the exact pixel in the mask if it is set (value = black or 1), and trigger if it is.

herpderp
  • 11
  • 1
0

Did you try to bunk two same pictures file and just for the second picture give it a short width ? Like that I think you will can to add differents listerners for the both pictures.

blue_diamond
  • 65
  • 3
  • 8
  • 1
    can you imagine this working for example with the shape of a star? Or even oval shape. – Yegoshin Maxim Jan 18 '12 at 14:55
  • you can't do it, if you can cut your picture in some pictures on Photoshop, Gimp and ohters for example...Otherwise you have to check manually coordinates... – blue_diamond Jan 18 '12 at 15:00