My problem is pretty hard to explain. First of all, I have :
A JPanel (leftPanel)
A JScrollPane (lBar), which is created to scroll the leftPanel (--> new JScrollPane(leftPanel))
A button that adds a new panel in the leftPanel on each click
Here's the result :
https://www.youtube.com/watch?v=VFXwh_vofQI
There are two problems :
With 4 or 5 clicks, the panels are overriding themselves (strange)
(secondary)
I would like the button + panels to look nicer (instead
of a BIG CENTERED button)
The code I use :
ActionsPanel panel = new ActionsPanel();
JScrollPane lBar = new JScrollPane(leftPanel);
lBar.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
The ActionsPanel class :
public class ActionsPanel extends JPanel
{
private JButton newAction;
public ActionsPanel(final Editor editor)
{
this.newAction = new JButton("New");
this.newAction.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
getActions().add(new Action());
refresh();
}
});
setLayout(new GridLayout(0, 1));
refresh();
}
public void refresh()
{
removeAll();
add(newAction);
for (Action action : getActions())
{
ActionPanel panel = new ActionPanel(action);
panel.revalidate();
panel.repaint();
add(panel);
}
revalidate();
}
}
The ActionPanel class :
public class ActionPanel extends JPanel
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D graphics = (Graphics2D) g;
setSize(getWidth(), 100);
setLayout(new GridLayout(2, 1));
graphics.setColor(Color.GRAY);
graphics.drawRect(0, 0, getWidth(), getHeight());
graphics.setColor(Color.BLACK);
graphics.setStroke(new BasicStroke(2));
graphics.drawRect(0, 0, getWidth(), getHeight());
graphics.drawString("Ordinal : " + getOrdinal(), 5, 15);
}
}
Related
The following is my code.
I think click the button, at least, a Color.CYAN block will be added into MainPanel, but it doesn't.
Could you please tell me how to achieve that? Thanks.
public class TestFrame extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
final TestFrame mainFrame = new TestFrame();
mainFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
mainFrame.setVisible(true);
});
}
public TestFrame() throws HeadlessException {
setTitle("Frame");
setSize(new Dimension(1000, 800));
final JPanel mainPanel = new JPanel();
final JButton button = new JButton("Test");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
mainPanel.add(new Unit());
}
});
mainPanel.add(button);
mainPanel.revalidate();
add(mainPanel);
}
class Unit extends JComponent {
public Unit() {
setSize(new Dimension(100, 100));
setBackground(Color.CYAN);
}
#Override
protected void paintComponent(Graphics g) {
final Graphics2D g2D = (Graphics2D) g;
g2D.drawString("Hello World", 10, 10);
}
}
}
Your Unit JComponent is likely being added to mainPanel in the ActionListener and thus the GUI, but it has no preferred size and so per the FlowLayout used by JPanels, it will size to [0, 0]. FlowLayouts (and most layout managers) do not respect a component's size but rather its preferredSize. Also, revalidate() and repaint() need to be called on the container (mainPanel) after Unit has been added so that the layout managers can do their laying out of components and to allow the OS to clear dirty pixels.
To solve this, give it a preferred size, preferably by overriding public Dimension getPreferredSize() but by calling setPreferredSize(...) if you must, and by calling revalidate() and repaint() after adding the component to the container.
Better still, add the component to the container using a CardLayout tutorial, but hide it by also adding an empty JLabel, again using a CardLayout, and then display the hidden component by calling CardLayout.show(...) from within ActionListener.
Side note: don't forget the super method within your painting method:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // add this ****
final Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2D.setFont(UNIT_FONT);
g2D.drawString("Hello World", textX, textY);
}
else you break the painting chain and may see unwanted artifacts or other problems
e.g.,
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class TestFrame extends JFrame {
private CardLayout cardLayout = new CardLayout();
private JPanel cardPanel = new JPanel(cardLayout);
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
final TestFrame mainFrame = new TestFrame();
mainFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
});
}
public TestFrame() throws HeadlessException {
setTitle("Frame");
setPreferredSize(new Dimension(1000, 800));
final JPanel mainPanel = new JPanel(new BorderLayout());
final JButton button = new JButton("Test");
button.addActionListener(e -> {
cardLayout.next(cardPanel);
});
JPanel btnPanel = new JPanel();
btnPanel.add(button);
mainPanel.add(btnPanel, BorderLayout.PAGE_END);
mainPanel.add(cardPanel);
add(mainPanel);
cardPanel.add(new JLabel(), "Foo");
cardPanel.add(new Unit(), Unit.class.getCanonicalName());
}
static class Unit extends JPanel {
private static final int PREF_W = 100;
private static final int PREF_H = 100;
private static final Font UNIT_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 60);
public Unit() {
setBackground(Color.CYAN);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2D.setFont(UNIT_FONT);
g2D.drawString("Hello World", 360, 350);
}
}
}
I'm trying to add two JPanels to a JFrame, one with a simple backround and another one with buttons etc. Either I get only buttons or only the background. I can't find a solution to my problem anywhere, so any help would be appreciated. I'm still new to Java, so please don't hate.
GuiMainMenu:
public class GuiMainMenu extends JFrame implements ActionListener, KeyListener {
private static final long serialVersionUID = -7936366600070922227L;
Color blue = new Color(114, 137, 218);
Color gray = new Color(44, 47, 51);
Color white = new Color(255, 255, 255);
ImagePanel panel = new ImagePanel(new ImageIcon("image.png").getImage());
public static int width;
public static int height;
JPanel p = new JPanel();
JPanel p1 = new JPanel();
JLabel l = new JLabel();
JLabel l1 = new JLabel();
JLabel l2 = new JLabel();
JButton b = new JButton();
JButton b1 = new JButton();
JButton b2 = new JButton();
String title = "-";
public GuiMainMenu() {
setSize(m.X, m.Y);
setTitle(title);
setResizable(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(this);
p.setLayout(null);
width = getWidth();
height = getHeight();
getRootPane().addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
width = getWidth();
height = getHeight();
addButtons();
addLabels();
}
});
addLabels();
addButtons();
add(p);
add(panel);
setVisible(true);
}
public void addLabels() {
l.setSize(width, height);
l.setLocation(5, -40);
l.setText("x");
l.setHorizontalAlignment(SwingConstants.LEFT);
l.setVerticalAlignment(SwingConstants.BOTTOM);
l.setForeground(blue);
l.setFont(new Font("Trebuchet MS", Font.PLAIN, 15));
l1.setSize(width, height);
l1.setLocation(-22, -40);
l1.setText("y");
l1.setHorizontalAlignment(SwingConstants.RIGHT);
l1.setVerticalAlignment(SwingConstants.BOTTOM);
l1.setForeground(blue);
l1.setFont(new Font("Trebuchet MS", Font.PLAIN, 15));
l2.setText("test label");
l2.setSize(width, height);
l2.setLocation(0, -75);
l2.setVerticalAlignment(SwingConstants.CENTER);
l2.setHorizontalAlignment(SwingConstants.CENTER);
l2.setForeground(blue);
l2.setFont(new Font("Trebuchet MS", Font.BOLD, 26));
p.add(l);
p.add(l1);
p.add(l2);
validate();
}
public void addButtons() {
b.setText("button0");
b.setFocusable(false);
b.setBorder(null);
b.setLocation(width / 2 - 200, height / 2 - 35);
b.setSize(400, 35);
b.setForeground(white);
b.setBackground(blue);
b.addActionListener(this);
b1.setText("button1");
b1.setFocusable(false);
b1.setBorder(null);
b1.setLocation(width / 2 - 200, height / 2 + 10);
b1.setSize(400, 35);
b1.setForeground(white);
b1.setBackground(blue);
b1.addActionListener(this);
p.add(b);
p.add(b1);
validate();
}
#Override
public void actionPerformed(ActionEvent arg0) {
}
#Override
public void keyPressed(KeyEvent arg0) {
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
}
ImagePanel Class:
class ImagePanel extends JPanel {
private static final long serialVersionUID = -7270956677693528549L;
private Image img;
public ImagePanel(String img) {
this(new ImageIcon(img).getImage());
}
public ImagePanel(Image img) {
this.img = img;
}
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, GuiMainMenu.width, GuiMainMenu.height, null);
}
}
p.setLayout(null);
Don't use a null layout. Swing was designed to be used with layout managers.
Read the section from the Swing tutorial on Layout Managers for more information and working examples.
Either I get only buttons or only the background
add(p);
add(panel);
The default layout manager for a JFrame is the BorderLayout. If you don't specify a constraint both components get added to the CENTER. However only the last one added will be displayed.
Try the following to see the difference:
add(p, BorderLayout.PAGE_STRT);
add(panel, BorderLayout.CENTER);
one with a simple backround and another one with buttons etc.
However above is not what you want. Swing components have a parent/child relationship. So what you really need is:
backgroundPanel.add(buttonPanel);
add(backgroundPanel, BorderLayout.CENTER);
Note I used more meaningful names because "p" and "panel" and not descriptive. Use descriptive names for variable so people can understand what they mean.
I suppose you want to display a JFrame with a background image and various components. I think after reviewing your code that there is some misunderstanding on your part causing the problem.
I've created a short snippet of code that does the basics and maybe helps you to solve your problem. (Not tested!)
#SuppressWarnings("serial")
public class GuiMainMenu extends JFrame{
private BufferedImage imageBackground; // TODO: load your background image
public GuiMainMenu(){
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(1024, 768));
setMinimumSize(new Dimension(800, 600));
// TODO: setLayout if needed
JPanel panel = (JPanel)add(new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(imageBackground, 0, 0, this);
}
});
addOtherComponents(panel);
pack();
setLocationRelativeTo(null);
setTitle("Your Title her");
setVisible(true);
}
private void addOtherComponents(JPanel panel){
//TODO: add the needed Stuff
//panel.add ...
}
}
I have a JPanel that acts as topbar for my application, I am trying to design the topbar buttons now, But I am facing an Issue.
as you can see when I hover over it the red is not filling the panel, I want the red to be a full square. and remain the same size for topbar and icon size. The result I expect is
as you can see the color is filled within the full bar. I would like to recreate this.
So here is the code as follows a Custom JButtonClass to create the Hover Effect.
public class LynxButton extends JButton {
public LynxButton(){
super.setContentAreaFilled(false);
}
public LynxButton(String text) {
super(text);
super.setContentAreaFilled(false);
}
#Override
protected void paintComponent(Graphics g) {
Color pressedColor = ThemeManager.red_LYNX.darker();
if (getModel().isPressed()) {
g.setColor(pressedColor);
} else if (getModel().isRollover()) {
g.setColor(pressedColor);
} else {
g.setColor(getBackground());
}
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
#Override
public void setContentAreaFilled(boolean b) {
}
}
and then we define the code using
LynxButton exitButton = new LynxButton();
exitButton.setIcon(...);
exitButton.setBorder(null);
I have tried to set the margin to see if it fixes the issue but again no luck with it.
exitButton.setMargin(new Insets(0, 0, 0, 0));
Edit: Forgot to show the JPanel Defination
JPanel buttonContainer = new JPanel(new FlowLayout(FlowLayout.RIGHT));
The buttonContainer fills the whole topbar, Confirmed it by removing the call to setBackgroundColor.
You didn't calculate the hgap and vgap from FlowLayout in. Those act like a natural border.
All you need to do is the alter the initialization of your JPanel to new JPanel(new FlowLayout(FlowLayout.RIGHT), 0, 0)
Example code:
public static void main(String[] args) {
JFrame f = new JFrame();
TestA b = new TestA("X");
JPanel buttonContainer = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
buttonContainer.setBackground(Color.GREEN);
buttonContainer.add(b);
f.add(buttonContainer);
f.pack();
f.setVisible(true);
}
TestA is your LynxButton
class TestA extends JButton {
public TestA() {
super.setContentAreaFilled(false);
}
public TestA(String text) {
super(text);
super.setContentAreaFilled(false);
}
#Override
protected void paintComponent(Graphics g) {
Color pressedColor = Color.RED;
if (getModel().isPressed()) {
g.setColor(pressedColor);
} else if (getModel().isRollover()) {
g.setColor(pressedColor);
} else {
g.setColor(getBackground());
}
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
#Override
public void setContentAreaFilled(boolean b) {
}
}
New to Java and very new to Java's GUI classes. I'm making a GUI to showcase a few games, but am having difficulties switching panels. I read about CardLayout but I'm having an issue implementing it because I can't get the JPanels that hold the different games' GUIs to send their events back to the class that uses the CardLayout. (This is probably where I'm going wrong -- I can't get my head around how to structure this properly.)
This is my main menu (called mainContainer):
This is the overall structure of the GUI driver:
public class CasinoDriverGUI {
//CardLayout is here in the main method Container contentPane.add(cardLayout)
public static void main(String[] args) throws IOException
//MainContainer is MenuScreen: GridBagLayout for nice button placement
static class MainContainer extends JPanel implements ActionListener{...}
static class CrapsContainer extends JPanel implements ActionListener{...}
static class PokerContainer extends JPanel implements ActionListener{...}
//Button with custom look
class CButton extends JButton
}//end CasinoDriverGUI
Here is the main method: It grabs an image from a website and then adds the menu screen (mainContainer) to the contentPane. The menu screen uses GridBagLayout, but it's where the button components are added. Because of this, I can't figure out how to get the CardLayout of the contentPane to listen to the menu screen's buttons. I tried using ContainerListener but that seemed to be a dead end.
public class CasinoDriverGUI {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
System.out.println("Loading finished. Starting the Casino!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);
// Starting the Swing GUI in the EDT
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final CardLayout cardLayout = new CardLayout();
JFrame frame = new JFrame("Midnight Casino");
// frame about the size of background src image
frame.setPreferredSize(new Dimension(580, 329));
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardLayout);
MainContainer mainContainer = new MainContainer();
mainContainer.setPreferredSize( frame.getPreferredSize() );
contentPane.add(mainContainer, "mainContainer");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
As I have it so far, I have just tried using the "menu screen" (mainContainer) to instantiate all the games' panels and use an ActionListener on some buttons to simply call thisGame.setVisible(true). but this is forcing the window to be minimized and re-opened for any change to be detectable.Edit: fixed this.
Any advice on how I can restructure this code to be able to switch the panels from the menu screen to the different game's panels? (Code is below, but the craps and poker GUIs are incomplete.. just using the code as placeholders.
public class CasinoDriverGUI {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
System.out.println("Loading finished. Starting the Casino!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);
// Starting the Swing GUI in the EDT
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final CardLayout cardLayout = new CardLayout();
JFrame frame = new JFrame("Midnight Casino");
// frame about the size of background src image
frame.setPreferredSize(new Dimension(580, 329));
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardLayout);
MainContainer mainContainer = new MainContainer();
mainContainer.setPreferredSize( frame.getPreferredSize() );
contentPane.add(mainContainer, "mainContainer");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
static class MainContainer extends JPanel implements ActionListener
{
public BufferedImage gradientImage = null;
public static BufferedImage textureImg; // static for ease
public static boolean loadingFinished = false;
protected JButton pokerJBtn;
protected JButton crapsJBtn;
CrapsContainer crapsContainer;
PokerContainer pokerContainer;
public MainContainer() {
setBorder(new EmptyBorder(50, 50, 50, 50)); // setting the insets
setLayout(new GridBagLayout());
// working with GridBagConstraints
GridBagConstraints labCnst = new GridBagConstraints();
GridBagConstraints txtCnst = new GridBagConstraints();
labCnst.ipady = txtCnst.ipady = 10;
labCnst.fill = GridBagConstraints.HORIZONTAL;
labCnst.gridwidth = 1;
labCnst.weightx = 0.3;
labCnst.gridx = 2;
labCnst.gridy = 2;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
pokerJBtn = new CButton("5-Card Poker");
add(pokerJBtn, labCnst);
labCnst.gridx = 2;
labCnst.gridy = 20;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
crapsJBtn = new CButton("Craps");
add(crapsJBtn, labCnst);
crapsContainer = new CrapsContainer();
pokerContainer = new PokerContainer();
add(crapsContainer);
add(pokerContainer);
crapsContainer.setVisible(false);
pokerContainer.setVisible(false);
//Add Action Listeners
crapsJBtn.addActionListener(this);
pokerJBtn.addActionListener(this);
}
public void changeCompFont(JComponent comp)
{
comp.setForeground(Color.WHITE);
comp.setFont(getFont().deriveFont(Font.BOLD, 13));
}
// To PAINT THE TEXTURE ABOVE THE COMPONENTS
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D)g.create(); // cloning
Rectangle2D txRect = new Rectangle2D.Double(0, 0, textureImg.getWidth(), textureImg.getHeight());
TexturePaint txPaint = new TexturePaint(textureImg, txRect);
g2d.setPaint(txPaint);
//make the texture transparent
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.233f));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();// disposing the graphics object
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if(gradientImage==null || gradientImage.getHeight() != getHeight() )
{
gradientImage = createGradientImg();
}
g2d.drawImage(gradientImage, 0, 0, getWidth(), getHeight(), this);
g2d.dispose();
}
public BufferedImage createGradientImg()
{
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
// background gradient paint, linear gradient paint for the background
// Gradient paint rendering could be made more optimized
LinearGradientPaint lgrPaint = new LinearGradientPaint(0.0f, 0.0f, getWidth(), getHeight(),
new float[] { 0.0f, 0.5f, 0.6f, 1.0f },
new Color[] { new Color(0x0530E),// new Color[] { new Color(0x002AFF),
new Color(0x0A31B),
new Color(0x0A31B),
new Color(0x0530E ) });
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setPaint(lgrPaint);
//g2d.shear(0.2, 0);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
g2d.drawImage(textureImg, 0, 0, getWidth(), getHeight(), null);
return image;
}
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == pokerJBtn)
{
pokerContainer.setVisible(true);
}
else if (e.getSource() == crapsJBtn){
this.setVisible(false);
invalidate();
crapsContainer.setVisible(true);
revalidate();
repaint();
}
}
}
//Either Flow, Border, or GridBag Layout
static class CrapsContainer extends JPanel implements ActionListener
{...}
//Either Flow, Border, or GridBag Layout
static class PokerContainer extends JPanel implements ActionListener
{...}
//Custom Button to change aesthetic look
class CButton extends JButton
{...}
}
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);
}
}
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);
}
}
}