My problem is that when adding a .GIF to a JPanel, it shows this black square background for the .GIF.
Result when adding on JPanel:
It happens when I use this line:
p2.add(loadBar); // where p2 = new JPanel();
However, when I add the same .GIF on the JFrame, the black square is not there anymore. Like this:
jf.add(loadBar); // where jf = new JFrame();
Result when adding on JFrame:
Part of the class code:
String loadLink = "http://i.imgur.com/mHm6LYH.gif";
URL ajaxLoad = null;
try {
ajaxLoad = new URL(loadLink);
} catch (MalformedURLException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
ImageIcon loading = new ImageIcon(ajaxLoad);
JLabel loadBar = new JLabel(loading);
loadBar.setBounds(70, 60, 54, 55);
loadBar.setOpaque(false);
//jf.add(loadBar);
p2.add(loadBar);
Could someone please explain why it is happening like this? Thank you for your time and reading.
EDIT:
// Creates the Initialization Panel
p2 = new JPanel();
// Sets the background, black with 125 as alpha value
// This is less transparent
p2.setLayout(null);
p2.setBackground(new Color(0,0,0,150));
// Sets a border to the JPanel
p2.setBorder(new LineBorder(Color.WHITE));
// Sets some size to the panels
p2.setBounds(20, 20, 200, 150);
// Adds the loading gif
String loadLink = "http://i.imgur.com/mHm6LYH.gif";
URL ajaxLoad = null;
try {
ajaxLoad = new URL(loadLink);
} catch (MalformedURLException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
ImageIcon loading = new ImageIcon(ajaxLoad);
JLabel loadBar = new JLabel(loading);
loadBar.setBounds(70, 60, 54, 55);
loadBar.setOpaque(false);
p2.add(loadBar);
That is the JPanel which is shown in the first image without the JLabel. I can't really show the JFrame part in the code because it is spread all over the class. But I don't think the problem is with JFrame so it could be this JPanel :/
Your problem is here...
p2.setBackground(new Color(0,0,0,150));
Swing does not support alpha based backgounds, either your component is transparent or it's not.
Doing this means that the component "attempts" to use the alpha value as the background fill color, but the paint manager doesn't know it should paint beneath the component, causing all sorts of problems and issues
Now, this a little tricky. You need to make the container transparent by using setOpaque(false)
, but this now means that the background is not painted.
What you need to do is create a custom component, set it's opaque
property to false
and override it's paintComponent
method and fill the background with your alpha based color. I normally like using a AlphaComposite
, but this works as wel...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class TranslucentPanelExample {
public static void main(String[] args) {
new TranslucentPanelExample();
}
public TranslucentPanelExample() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
JLabel background = new JLabel(
new ImageIcon(ImageIO.read(
getClass().getResource("/background.jpg"))));
background.setLayout(new GridBagLayout());
background.add(new WaitPane());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(background);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
public class WaitPane extends JPanel {
public WaitPane() {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(12, 12, 12, 12));
// This is very important
setOpaque(false);
setBackground(new Color(0, 0, 0, 150));
String loadLink = "http://i.imgur.com/mHm6LYH.gif";
URL ajaxLoad = null;
try {
ajaxLoad = new URL(loadLink);
} catch (MalformedURLException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
ImageIcon loading = new ImageIcon(ajaxLoad);
JLabel loadBar = new JLabel(loading);
loadBar.setHorizontalAlignment(JLabel.CENTER);
loadBar.setVerticalAlignment(JLabel.CENTER);
add(loadBar);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
}
}
Layout managers, layout managers, layout managers...
I can't stress enough how important layout managers are. You are relying on "magic" numbers which may not always meet reality...
Looking at your code, I see nothing wrong. Just to be sure, I tested your code out as is, adding in my own JFrame and JPanel. Here is what I ended up with:
import javax.swing.*;
import java.net.*;
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
frame.setSize(600, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
String loadLink = "http://i.imgur.com/mHm6LYH.gif";
URL ajaxLoad = null;
try {
ajaxLoad = new URL(loadLink);
} catch (MalformedURLException e3) {
e3.printStackTrace();
}
ImageIcon loading = new ImageIcon(ajaxLoad);
JLabel loadBar = new JLabel(loading);
loadBar.setBounds(70, 60, 54, 55);
loadBar.setOpaque(false);
panel.add(loadBar);
frame.add(panel);
frame.setVisible(true);
}
}
When I ran it, it worked as it should, without any problems. The .GIF was animated and in its proper place in the frame. Could you copy the code above and test that it works for you the same way? Also, could you show us your code in which you initialize your JFrame and JPanel that contain the image? Thanks.
It's taking time to load the image as per your first snapshot.
Please have a look at Monitoring with an ImageObserver to check the status of the image.
Add the image in JPanel
when its fully loaded.
Sample code:
new Thread(new Runnable() {
@Override
public void run() {
int width = loading.getIconWidth();
if (width >= 0) {
isImageLoaded = true;
p2.add(loadBar);
return;
}
// Wait if the image is not loaded yet
while (!isImageLoaded) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
}
}
}
}).start();