How to fix a JLabel transparency error? - java

I am new to Java, What I am trying to do is simple, I want to make a JLabel have a transparent color when the mouse enters the label area and get the label to its original color when the mouse leaves the label area.
I suppose this is simple and in my code works but I get a strange effect when the mouse is on the label. This is the code that I use:
In the event mouseEntered of the label:
private void lblNuevoCLMouseEntered(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
bgcolor=(new Color(0, 0, 0, 100));
lblNuevoCL.setBackground(bgcolor);
}
In the event mouseExited:
private void lblNuevoCLMouseExited(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
lblNuevoCL.setBackground(new java.awt.Color(206,206,255));
}
This is what happens when the mouse enters the label( the square to the left of the image):
it gets transparent using an RGB color with alpha but apart from getting transparent
a strange background appears on the label as you see in the picture.

Make the JLabel opaque to allow the background color to be set
lblNuevoCL.setOpaque(true);

What you need to do is to make the background of the JLabel magically disappear. The way to do this is to use setOpaque().
What setOpaque does is this (taken from docs):
If true the component paints every pixel within its bounds.
Otherwise, the component may not paint some or all of its pixels,
allowing the underlying pixels to show through.
The last line has the solution to your problem.
When the mouse enters, you use lblNuevoCL.setOpaque(false); to make it have a transparent
background
lblNuevoCL.setOpaque(true); when the mouse exits so that it goes back to its original colors. That way, you do not have to worry about what color the background is.
Remember that Ubuntu's JLabel will have a different background color than that of Windows. hardcoding the color can cause it to look weird.

it gets transparent using an RGB color with alpha
See Backgrounds With Transparency for an explanation (and a couple of solutions) of the problems you will have when you use transparency.

Related

Creating a "face" code with manipulation capabilities

I have an assignment where I am supposed to create a prototype drawing program to display and manipulate faces. It is supposed to use 2 windows, one to draw the face and the other to control the drawing. It is supposed to initially show the image of a face (drawn with shapes).
The face consists of a head, two eyes, a nose, and a mouth. Each of these parts is selected by clicking the mouse within the border of the object. The eyes are selected as a pair, so clicking either eye selects them both. when one face part is selected, all previous selections are forgotten.
The control window operates only upon the selected object. A click on the Change image button performs the following tasks (depending on the selected face part):
Head: Head changes from green to yellow to purple to purple, and back to green
Nose: The nose image changes another of three possible nose images
Mouth: Mouth image changes to another of three possible mouth images
Eyes: eye image changes to another of four possible eye images
Include a scroll bar with behavior:
Selected Head: Head gets wider and narrower with scroll bar value change
Selected Nose: Nose image moves up or down with scroll bar value change
Selected Mouth: Mouth gets wider or narrower with scroll bar value change
Selected Eyes: Eyes move closer together or farther apart with scroll bar value change
My problem is, I have no idea where to even start. I have watched many a tutorial on swing and awt and have even tried playing around with the palette manager in NetBeans. Can anyone point me in the right direction or maybe walk me through the code?
Your question is not a good fit here. Also, despite your instructors alleged inaccuracies, it is still conceivably possible for a person to do the research on their own to go from the rather nice set of specific requirements you have to a functioning program. I don't mean that to be as critical as it may sound.
However, out of appreciation of the fact that you approached your instructor, and also out of pity, maybe I can give you some starting points and hints.
First of all, Swing is the right way to start. Read through the relevant sections of the tutorial at http://zetcode.com/tutorials/javaswingtutorial/ and follow along with some of the projects.
You can code Swing interfaces by hand quite easily, and for your relatively simple application, and for the learning experience, it is a reasonable option. However, for future reference, many IDEs have GUI editors (NetBeans ships with the feature I think, Eclipse has the WindowBuilder plugin) - the caveat being that you have to add learning how to use the IDE to your task list (of course, this will ultimately save you time in the long run).
In any case, your first step should be to design your software. Determine what actions you need to perform, what user actions you need to respond to and how, and what information you are working with. You give the following requirements:
The control window operates only upon the selected object. A click on
the Change image button performs the following tasks (depending on the
selected face part):
Head: Head changes from green to yellow to purple to purple, and back
to green
Nose: The nose image changes another of three possible nose
images
Mouth: Mouth image changes to another of three possible mouth
images
Eyes: eye image changes to another of four possible eye images
Include a scroll bar with behavior:
Selected Head: Head gets wider and narrower with scroll bar value
change
Selected Nose: Nose image moves up or down with scroll bar
value change
Selected Mouth: Mouth gets wider or narrower with scroll
bar value change
Selected Eyes: Eyes move closer together or farther
apart with scroll bar value change
The basic component you are working with here is a face, so let's make a design decision here to have a face be an object with other properties (you could take a different approach and have the different parts of the face be your basic units). Based on your description of scroll bars, a face has the following modifiable properties:
Head width.
Vertical nose position.
Mouth width.
Distance between eyes.
A face also, of course, has other constant characteristics that are pretty much up to you to arbitrarily decide the value of, for example the diameter of the eyes, the color of the skin, etc. You will have to work those out.
In addition to modifying the above properties, there are a few things you need to be able to do with a face, also based directly on your requirements:
Draw (paint) the face.
Redraw (repaint) the face when a property changes.
Allow the user to select a part by clicking, which breaks down into:
Responding to mouse clicks.
Determining the component under the cursor given an XY location.
Providing information about the selection to the application.
The last part "providing information about the selection" is an implementation detail that you have a few options for, and you will have to decide. For example, you could create some type of event listener interface and tell the face about it, and let it call methods on that interface when the selection changes -- this is a very swing way to do it. You could also have the face internally maintain which property is currently selected, in which case you need to give it the ability to get/set the value of the currently selected property. You could also have the face directly call methods on your editor UI window. All of these ways have distinct advantages and disadvantages, and I'll leave it as an exercise to the reader to experiment.
Now, you also, as per your requirements, need to provide a scroll bar for the user to edit properties with, in a separate window. So now, think about what UI components you need and how you want them to tie together:
Face Window
Contains a single face component (or more if you want).
Editor Window
Contains a scroll bar.
Might contain a label describing the current selection, if you'd like.
Swing already provides most of these components. A window is a JFrame. A scroll bar is a JScrollBar. A label is a JLabel. Swing doesn't provide a face, so you'll need to write a custom component yourself.
As for how they tie together:
Changing the object selection in the face could:
Update the scrollbar to the current value, if you'd like.
Update the scrollbar range to appropriate values.
Update the label to describe the current selection, if you'd like.
Changing the scrollbar must:
Update the currently selected property on the face.
Ultimately cause the face to be redrawn.
The major task now, then, is to implement a Swing component that draws a face and responds to mouse clicks.
Since you are creating a new component, you'll want to pick an appropriate base, perhaps a JComponent or a JPanel, up to you. Exactly how to create new components can be easily found in many tutorials on Google (including some basics in the one I linked to above), and that is up to you to research. Essentially, though, reiterating what was said above, your custom face component has the following custom behaviors:
Draw a face.
Receive mouse events.
Determine clicked component from mouse X,Y coordinates. At its most basic level, this will require some math. If your head, eyes, mouth, and nose are ellipses, for example, it will be up to you to compute whether or not a given X,Y coordinate is within the bounds of one of those ellipses. However, you will want to look into Shape, which will allow you to easily define shapes and provides bounds checking methods already.
I think this is enough for you to get started and put it all together. The following general tasks are at hand:
Read that tutorial I linked to, a lot of basics should become clear. Try writing some simple "hello world" style applications.
Try writing some custom components; your requirements are basic and much of it is covered in the "Painting" section of that tutorial.
Check out a tutorial or some examples on how to use Shape and experiment.
If you have specific questions about code you've written, with a specific problem you may be trying to solve, you can always come back and post that on SO.
I hope this helps. More importantly, I hope this gives you at least some idea of how to go from requirements to implementation in general.
Edit:
It's been a while since I played with Shape so I put together this tiny example. Click / drag over the two shapes to select them, which will turn them yellow:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ShapeSelect extends JPanel {
private final Shape firstShape = new Rectangle2D.Float(60, 40, 70, 70);
private final Shape secondShape = new Ellipse2D.Float(30, 30, 90, 50);
private Shape selected = null;
public ShapeSelect () {
// set up the component
setPreferredSize(new Dimension(200, 200));
addMouseMotionListener(new MouseMotionAdapter() {
#Override public void mouseDragged (MouseEvent event) {
selectShapeUnder(event.getX(), event.getY());
}
});
addMouseListener(new MouseAdapter() {
#Override public void mousePressed (MouseEvent event) {
selectShapeUnder(event.getX(), event.getY());
}
});
}
// draw our shapes, selected shape is yellow.
#Override protected void paintComponent (Graphics g) {
Graphics2D graphics = (Graphics2D)g;
graphics.setColor((selected == firstShape) ? Color.YELLOW : Color.RED);
graphics.fill(firstShape);
graphics.setColor((selected == secondShape) ? Color.YELLOW : Color.GREEN);
graphics.fill(secondShape);
}
// updates 'selected' based on x,y coordinate and redraws component on change.
public void selectShapeUnder (int x, int y) {
Shape oldSelected = selected;
// note that since second shape is draw on top of first, we give second preference.
// for overlapping shapes the selection should be consistent with the gui display.
if (secondShape.contains(x, y))
selected = secondShape;
else if (firstShape.contains(x, y))
selected = firstShape;
else
selected = null;
if (selected != oldSelected)
repaint();
}
public static final void main (String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override public void run () {
JFrame frame = new JFrame("Shape Select");
frame.getContentPane().add(new ShapeSelect(), BorderLayout.CENTER);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

Faulty repaint() of swing components when using custom background colors

When I use JCheckboxes or JScrollPane (applied to the main component that holds all others in order to generate a scrollable window) together with components that use
component.setBackground(new Color(R, G, B, A));
to define their background color, I am getting some obnoxious repaint() issues. Hovering over JCheckboxes activates MouseListener and the background of the JCheckbox will suddenly display a random other part of the window. This remains even when taking the mouse off the JCheckbox.
The issue disappears when using
JCheckbox.setRollOverEnabled(false);
BUT will still occur when selecting the checkbox!
The scrollpane will also not properly repaint. ONLY the parts that are outside of the visible frame will be painted several times in a row in direction of scrolling when they come back into the frame. It looks similar to that error on Windows OS when a program crashes and you can "draw" with the window on the screen because it "generates" a new window every time you move it (http://i.stack.imgur.com/L5G5Q.png).
The most interesting part is that the issue completely disappears when I use
Color.grey (or any other pre-generated color)
It also disappears when not selecting a custom background color at all.
So is there an issue with revalidate() and repaint() hidden anywhere in this? Is the use of RGBA a problem, specifically the A (= opacity) part since Color.AnyColor works?
Is the use of RGBA a problem, specifically the A (= opacity) part
Yes, Swing does not support transparent backgrounds.
Swing expects a component to be either:
opaque - which implies the component will repaint the entire background with an opaque color first before doing custom painting, or
fully transparent - in which case Swing will first paint the background of the first opaque parent component before doing custom painting.
The setOpaque(...) method is used to control the opaque property of a component.
In either case this makes sure any painting artifacts are removed and custom painting can be done properly.
If you want to use tranparency, then you need to do custom painting yourself to make sure the background is cleared.
The custom painting for the panel would be:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
panel.setOpaque(false); // background of parent will be painted first
Similar code would be required for every component that uses transparency.
Or, you can check out Background With Transparency for custom class that can be used on any component that will do the above work for you.

A nested JPanel's background image is not re-drawn correctly

I used ImageIO.read to get image (BackgroundImage) and painted the background image like this :
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, backDim.width, backDim.height, null);
}
and I added some component on that JPanel (background color of the panels inserted into it is new Color(0,0,0,0) (Transparent).
The background image is shown correctly when started; however, when I drag it to the bottom edge of the screen, half of them is erased. When I drag it to the left or right edge of the screen, it is re-drawn.
Ahh, and when I removed the Box.createRigidArea() gap, only the background of the titles are shown correctly. Other space is just the default color of a JPanel (light-gray).
EDIT: I added a component listener to make the screen drawn every time I move the window, but it calles repaint frequently so the computer might be overloaded. Is there any other solutions?
EDIT: The problem is that some (or most) of the drawn image is erased when I move the window (which contains the nested JPanel with a background image) to the bottom of the screen and drag it back. However, the repaint() is not called.
Final edit: Solved. It was because I did not call setOpaque(false);
background color of the panels inserted into it is new Color(0,0,0,0)
(Transparent)
A JPanel's opacity is true by default. If you set a transparent background color, you need to set the opacity to false - otherwise you will get painting artefacts (as you experienced)
panel.setBackground(transparentColor);
panel.setOpaque(false);

ToolTip for own drawings

my java application contains a JPanel on which I draw certain shapes. Now I would like to label these shapes with some kind of tooltips.
Therefore I tried to create my own "Tooltips" by using the drawString, setBackground, setColor method.:
public void drawToolTip(Graphics2D graphics, String text, Point2D position) {
graphics.setBackground(Color.RED);
graphics.setColor(Color.GREEN);
graphics.drawString(text, (float) position.getX(), (float) position.getY());
}
Unfortunately the setBackground method does not seem to work. The text background remains transparent although I set it to red. setColor and drawString just work fine.
My questions are:
What could be the reason that the setBackground method does not work?
Is there a possibility to draw a boarder arround the text without drawRect?
If I want to use "drawRect" method as a substitude to draw the text background and border: How can I make it automatically fit to the written text? Or in other words how can I get the dimensions of a specific text?
Regards Marc
Graphics2D.drawString() does not draw a background by default. You will have to do this yourself.
You can use drawRect() to draw a line border or fillRec() to draw a solid rectangle.
Oracle has a great tutorial on measuring String widths. Essentially, you need to create a java.awt.Font then get its FontMetrics and use that to calculate the width and height of your string.
A simple implementation would involve drawing onto the Graphics object of a JLabel's icon. And then simply adding the tool tip text to the Swing component.
For more information, see How to Use Tool Tips.
You can not change background color the way you expect using graphics.setBackground(..) call. Setting background color in the Graphics2D only affects the clearRect or fillRect kind of calls and not the background color of the Component.
For drawing a rectangle at a location you wish, with specific back ground, you will have to relay on following steps:
Define a rectangle - r
grpahics.setPaint() for background and
graphics.fill(r) graphcis.setPaint() for border and
graphics.draw(r) to draw border
now, comes the difficult part of drawing text in to the rectangle which involves computation of height etc. based on FontMetrics of the font you would set for drawing the text.
I googled and found an example for you here

Adding a watermark to a JTextArea

Is they a way of adding a watermark to a JTextArea?
I suspect that you'd need to subclass JTextArea and override the paintComponent() method, drawing your background image first and calling super.paintComponent() to render the text:
public void paintComponent (Graphics g) {
g.drawImage(watermark, 0, 0, this);
super.paintComponent(g);
}
edit: as pointed out by camickr, a JTextArea is opaque, so your subclass will need to change this by calling setOpaque(false).
I doubt the suggestion given above will work. A JTextArea is opaque, so the text will paint over top of the image. So at the very least you will need to make the text area non-opague and you will then need to play with the background colors of the viewport and/or scrollpane.
If you want a reusable solution try creating an ImageBorder. The order of painting is:
a) paintComponent
b) paintBorder
c) paintChildren
So if you add the border to the text area it will paint on top of the text in a fixed location.
Or if you add the border to the viewport it will paint below the text is a floating location.
You may also consider using JXLayer which can create quite complex visual effects

Categories