问题
I am trying to overlay a JSlider on top of a JProgressBar. I am using a JLayeredPane to hold the two components. I am adding the JProgressBar to the JLayeredPane and then adding the JSlider. So far, I have attempted to make the JSlider transparent by setting opaque to false and overriding the paintComponent method. What I end up with is that the slider handle is the only part that becomes transparent while the background stays opaque. It is possible that I am not using the JLayeredPane correctly, but my tests with JLabels seemed to work. How do I get the background of the JSlider to be transparent?
JSlider slider = new JSlider()
{
@Override
public void paintComponent(java.awt.Graphics g)
{
java.awt.Graphics2D g2 = (java.awt.Graphics2D) g;
g2.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, (float) 0.5));
super.paintComponent(g2);
}
};
Thank you all for your help. Through your examples, I have discovered that my issue is with the JLayeredPane that I am using. I recognize that the JSlider background can be made transparent, however, I still cannot get the components on layers beneath to show through. This is my example:
public class SliderTest extends JFrame
{
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
SliderTest frame = new SliderTest();
frame.setVisible(true);
} catch (Exception e)
{
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public SliderTest()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panel = new JPanel();
contentPane.add(panel, BorderLayout.CENTER);
panel.setLayout(new BorderLayout(0, 0));
JLayeredPane layeredPane = new JLayeredPane();
panel.add(layeredPane, BorderLayout.CENTER);
layeredPane.setLayout(new BorderLayout(0, 0));
JProgressBar progressBar = new JProgressBar();
progressBar.setValue(50);
layeredPane.add(progressBar);
layeredPane.setLayer(progressBar, 0);
JSlider slider = new JSlider()
{
@Override
protected void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
super.paintComponent(g);
}
};
layeredPane.setLayer(slider, 1);
slider.setOpaque(false);
// layeredPane.setLayer(slider, 1);
layeredPane.add(slider, BorderLayout.CENTER);
}
}
回答1:
This will depend upon what it is you want to achieve. By default JSlider
is transparent.
What's important here is that the opaque property MUST be false
, otherwise the repaint manager will not paint behind the components...
- Top slider, transparent background (blue), opaque control
- Middle slider, transparent background (green), transparent control
Bottom slider, normal
JSlider
public class TestSlider {
public static void main(String[] args) { new TestSlider(); } public TestSlider() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { public TestPane() { setBackground(Color.RED); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.HORIZONTAL; add(new TransparentBackgroundSlider(), gbc); add(new TransparentSlider(), gbc); add(new JSlider(), gbc); } } public class TransparentBackgroundSlider extends JSlider { public TransparentBackgroundSlider() { // Important, we taking over the filling of the // component... setOpaque(false); setBackground(Color.BLUE); } @Override protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setColor(getBackground()); g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f)); g2d.fillRect(0, 0, getWidth(), getHeight()); g2d.dispose(); super.paintComponent(g); } } public class TransparentSlider extends JSlider { public TransparentSlider() { // Important, we taking over the filling of the // component... setOpaque(false); setBackground(Color.GREEN); } @Override public void paint(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f)); super.paint(g2d); g2d.dispose(); } @Override protected void paintComponent(Graphics g) { // We need this because we've taken over the painting of the component Graphics2D g2d = (Graphics2D) g.create(); g2d.setColor(getBackground()); g2d.fillRect(0, 0, getWidth(), getHeight()); g2d.dispose(); super.paintComponent(g); } }
}
Update with layer example
public class TestSlider {
public static void main(String[] args) {
new TestSlider();
}
public TestSlider() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JLayeredPane {
private JProgressBar pb;
private JSlider slider;
public TestPane() {
pb = new JProgressBar();
slider = new JSlider();
add(pb, new Integer(0));
add(slider, new Integer(1));
}
@Override
public Dimension getPreferredSize() {
Dimension size = pb.getPreferredSize();
size.height *= 4;
size.width = Math.max(size.width, slider.getPreferredSize().width);
return size;
}
@Override
public void doLayout() {
super.doLayout();
int width = getWidth();
int height = getHeight();
Dimension size = pb.getPreferredSize();
int x = 10;
int y = (getHeight() - size.height) / 2;
pb.setLocation(x, y);
size.width = getWidth() - 21;
pb.setSize(size);
size = slider.getPreferredSize();
x = (getWidth() - size.width) / 2;
y = (getHeight() - size.height) / 2;
slider.setBounds(x, y, size.width, size.height);
}
}
}
来源:https://stackoverflow.com/questions/14534910/how-do-i-make-a-jslider-background-transparent-or-how-do-i-properly-overlay-jco