Java. Swing. JComponent's clickable area - java

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?

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.

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.

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.

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.

Related

How do I change the color of an actual JButton in Java? Not the background and not the text

button[currRow][currCol].setBackground(Color.RED);
button[currRow][currCol].setContentAreaFilled(true);
button[currRow][currCol].setOpaque(true);
That's what I have right now for my connect four game to denote a red player's move.
At the moment, it only colors the background and if I change my code to button[currRow][currCol].setForeground(Color.RED) then the whole thing just appears to not change. How would I fix this?
This is not easily achievable. The problem is that the pluggable look and feel paints the button content, and it does so in whatever way it sees fit. For instance, some L&F might paint a gradient which does not use the background color.
I suggest for a case such as yours to use a custom image (JButton.setIcon()) and no content area (JButton.setContentAreaFilled(false)).
Alternatively, you could create a custom component which draws the element itself, overriding JComponent.paintComponent().

How do I change the color of a drawn item after pressing a JButton? [duplicate]

This question already has an answer here:
How to define multiple JButton actions from a different class
(1 answer)
Closed 6 years ago.
So the program draws a car and I'm going to make three buttons, one for flash to initialize the flashing ability, one left, to move the car one space to the left and one right, to move the car one space to the right. My question is how do I make it change color each time I press the button? So to sum it up, I don't know how to have an object change it's color each time the button is pressed while flashing is on. I assume I use paint()
Any help would be appreciated.
If you are drawing an image, you will need to load a different image file which is a different color, and then draw that image instead. You will do this inside whatever method you are currently using to draw the car.
If you are drawing a shape or text of some kind, you can call g.setColor() on the graphics object passed to the paint() or paintComponent() method before drawing the shape.
There are any number of ways to do it. The basic requirement though, is to have a Object of some kind which you can tell when it should change color, it would then undertake the appropriate action and update the UI accordingly.
You could...
Use a simple JPanel as the representation of the object and simply call it's setBackground color method when you want it to change color.
This assumes you want to make use of a LayoutManager to position the panel. While it is certainly doable, it will require some thought into the overall design
You could...
Use a JPanel and override it's paintComponent method and paint the color change there. At the simplest level, this is overkill, but if you also want to draw a "car" or an image of "car", then this becomes a little more meaningful, especially if you want to rotate the car based on the direction it's moving
See Painting in AWT and Swing, Performing Custom Painting and 2D Graphics for more details
Flashing
I assume you mean you want the object to be animated in some way and "blink" on and off.
This can easily be accomplished through the use of a Swing Timer which can be used to change the state of a simple flag which changes the way in which the component is rendered.
See How to use Swing Timers for more details
The important concept to take away from this is to create a object which encapsulates the requirements in away which is ease for you to use, so when you enable flashing for example, all you do is call the setFlashing(boolean) method and the object takes care of the rest

Java - Getting screen position of buffered image

I'm working with some code where I have a few buffered images in a scrollbar. When I click one of these images, I want to draw a rectangle around the image to indicate that the image is selected.
My issue is that because my panel is scrollable, the image position set when drawing is not necessarily the actual screen position. So when the mouse is clicked, the point of the cursor's position doesn't intersect any of the position attributes (x, y, height, & width) I have for the object holding the actual image.
Does anybody know how to get the actual position of an image relative to the screen instead of the panel?
So far I haven't found any solutions to this online.
Thanks.
You can use the SwingUtilities.convertPoint(...) method.
I would guess you need to convert the mouse point the coordinates of the viewport of the scroll pane.
Maybe an easier approach is to use a JList with a custom renderer. You can set the JList to wrap components horizontally. Then in you custom renderer you just add a Border to the selected item. Read the section from the Swing tutorial on How to Use Lists for more information and examples.

How can I get a certain RGB value from a canvas painted with LinearGradientPaint?

I have used the LinearGradientPaint class to draw a rectangle dynamically filled with user-defined colors. This happens by overriding the paintComponent method.
Here is how it looks like:
.
You can see the small thumbs/ handle on top. The user can move these around, delete them, and add new ones. They can also change the color. As a result the user can completely customize how the gradient looks like. This works just fine so far, no issue.
What I need now, and I tried searching for this info, is to get RGB-values anywhere on this gradient.
I only know the x-amount of colors that LinearGradientPaint uses to generate the gradient. I know at what point (fraction) these colors are located (the number below the gradient box, corresponding with the 'thumbs' on top.
Is there anyway to get the colors in between the RGB-values which are used to generate the gradient? In my example above I mean the darkened red or green areas.
If this really is a linear gradient between new Color(r1,g1,b1) and new Color(r2,g2,b2), then the colour at x, where 0 <= x <= 1 is
new Color((int)(r1*(1-x)+r2*x),(int)(g1*(1-x)+g2*x),(int)(b1*(1-x)+b2*x));
Of course, I have no idea whether this is the formula that is actually used inside LinearGradientPaint - but it ought to be something equivalent to this.
A way you might be able to do this, is to create a 1 pixel high BufferedImage of the same width of your component, render the gradient to it and simple use something like BufferedImage#getRGB.
This will return a int packed color value, which you can then use Color(int) to return a Color object, which makes it easier to extract the color components of the pixel.
Of course, this would all be easier if you used the BufferedImage as your primary output as well, then you would only have to create it once and because you'd be updating the image so it could be rendered to the screen, it would also be up-to-date

Java sampling pixel color in swing

I have to create a special TextFieldUI that draws an image as the background. That image contains some alpha components. However, whenever a character is written in that text field, first it redraws the background and then draws the character. This is fine when the background contains no alpha components, but after a few characters have been typed, the alpha areas sum up to become black.
The only way I can see around this is in the paintBackground method of TextfieldUI (which I'm overriding), I have to first sample the color of the background at that location, paint the entire graphics component that color, and then paint my background.
Does anyone know how to sample the color of a pixel when all I have access to is the Graphics object?
Is there a better way to draw a custom image as the textfield background other than overriding paintBackground in TextfieldUI?
Thanks
I haven't tried it before, but Swing is built on top of AWT, and the Robot class had a way of sampling specific pixels in the AWT
Well, I don't know what your custom code looks like in the paintBackground method, but I would make sure you fill in the text field background before you draw the image.
I'll let you decide if its "better" or not, but you can use the Background Panel which allows you to add an image to a panel. Then you add the text field to the panel (the text field is automatically made non-opaque so the image shows through). Then you add the panel to the GUI.
If that doesn't work then it would be nice to have a demo of your code so we can see whats actually happening.
When you override paintBackground, you're calling the superclass version first, right? It already lays down a background-color rectangle that would give your image a fresh-start.
Rather than 'sampling' the background color, it's probably already correct (the superclass paintBackground code gets it from the parent component if not locally set). If that default is not correct, set it in initial interface construction. (Your field isn't being overlaid on other complicated arbitrary interface of unknown solid colors, is it?)

Categories