I've done several inspection and done research on how to make a single panel transparent so that the image underneath it will show but has been unsuccessful with panels on a JTabbedPane
. I have setOpaque(false)
and setBackground(new Color(0,0,0,20))
on both the panels of the JTabbedPane
and also did the same on the JTabbedPane
itself. However, I still can't get the image on the back of the tabbed pane to show. What else am I missing here?
tabbePane.java
package tabbedpanetransparencypractice;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.*;
public class tabbedPane extends JTabbedPane{
JPanel tab1panel = new JPanel();
JPanel tab2panel = new JPanel();
public tabbedPane(){
this.setPreferredSize(new Dimension(400,400));
this.setBackground(new Color(0,0,0,20));
this.setOpaque(false);
tab1panel.setBackground(new Color(0,0,0,20));
tab2panel.setBackground(new Color(0,0,0,20));
tab1panel.setOpaque(false);
tab2panel.setOpaque(false);
this.addTab("Tab 1", tab1panel);
this.addTab("Tab 2", tab2panel);
}
}
topPanel.java
package tabbedpanetransparencypractice;
import javax.swing.*;
import java.awt.*;
public class topPanel extends JPanel{
Image myBG = new ImageIcon(getClass().getClassLoader().getResource("Assets/loginBg.jpg")).getImage();
@Override
public void paintComponent(Graphics g){
g.drawImage(myBG,0,0,getWidth(),getHeight(),this);
}
public topPanel(){
addTabbedPane();
}
public void addTabbedPane(){
tabbedPane tabbedpane = new tabbedPane();
this.add(tabbedpane);
}
}
frame.java
package tabbedpanetransparencypractice;
import java.awt.Dimension;
import javax.swing.*;
public class frame extends JFrame{
topPanel myPanel = new topPanel();
public frame(){
this.setPreferredSize(new Dimension(600,600));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.pack();
this.setLocationRelativeTo(null);
addComponents();
}
final void addComponents(){
this.setContentPane(myPanel);
}
}
main.java
package tabbedpanetransparencypractice;
public class main {
public static void main(String[] args) {
frame myFrame = new frame();
}
}
This is the output I get (I want the tab1 and tab2 to be transparent to reveal the bg image underneath)
I'd appreciate any help. Thanks.
First, Swing DOES NOT know how to deal with component's whose background colors are alpha based but which are opaque. Swing only knows how to deal with fully opaque and fully transparent components.
Using alpha based colors will generate weird and random paint artefacts. The simple answer is, you should never apply a alpha based color to a component's background (the only exception is JFrame
- thanks Sun :P)
The primary solution is, fake it.
That is, make the component transparent (setOpaque(false)
) and paint the background at a reduced alpha level. You can then use a alpha based color (because the component is no longer reliant on the color, as it's transparent), but I tend to just use a AlphaComposite
as it's generally easier to control and manipulate.
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
BackgroundPane bp = new BackgroundPane();
bp.setLayout(new BorderLayout());
bp.setBorder(new EmptyBorder(20, 20, 20, 20));
SeeThroughTabbedPane tp = new SeeThroughTabbedPane();
tp.setAlpha(0.5f);
tp.addTab("Tab 1", new TestPane("I be see through"));
tp.addTab("Tab 2", new TestPane("But you can't see me"));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(bp);
frame.add(tp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane(String text) {
setOpaque(false);
setLayout(new GridBagLayout());
JLabel label = new JLabel(text);
label.setForeground(Color.WHITE);
add(label);
}
}
public class BackgroundPane extends JPanel {
private BufferedImage bg;
public BackgroundPane() {
try {
bg = ImageIO.read(new File("/Volumes/Disk02/Dropbox/MegaTokyo/megatokyo_omnibus_1_3_cover_by_fredrin-d4oupef 50%.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return bg == null ? new Dimension(200, 200) : new Dimension(bg.getWidth(), bg.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bg != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - bg.getWidth()) / 2;
int y = (getHeight() - bg.getHeight()) / 2;
g2d.drawImage(bg, x, y, this);
g2d.dispose();
}
}
}
public class SeeThroughTabbedPane extends JTabbedPane {
private float alpha;
public SeeThroughTabbedPane() {
setOpaque(false);
setAlpha(1f);
}
public void setAlpha(float value) {
if (alpha != value) {
float old = alpha;
this.alpha = value;
firePropertyChange("alpha", old, alpha);
repaint();
}
}
public float getAlpha() {
return alpha;
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
g2d.setComposite(AlphaComposite.SrcOver.derive(getAlpha()));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
super.paintComponent(g);
}
}
}
Remember, anything you added to the JTabbedPane
which is still opaque will remain so, not in my TestPane
's constructor, I set the panel's opaque state to false
You might also like to take a look at Painting in AWT and Swing and Performing Custom Painting