Search code examples
javaswingjpaneljlabeljscrollpane

fixing JScrollPane with JLabel


In order to add a background Image , I work on JLabels instead of JPanel .

    JFrame frame=new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JLabel label=new JLabel(new ImageIcon("bg.png"));
    label.setLayout(new BoxLayout(label, BoxLayout.Y_AXIS));
    for(int i=0;i<20;i++)
         label.add(new JLabel(i.toString()));
    frame.add(label);

the problem here is that only components that fit the background image will be shown (in my example only the 10 first JLabels)

I tried using a JScrollPane

    JScrollPane scroll=new JScrollPane(l);
    for(int i=0;i<20;i++)
         label.add(new JLabel(i.toString()));
    frame.add(scroll);

but it didn't change much , so I tried using a JPanel

    JPanel panel=new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
    JScrollPane scroll=new JScrollPane(panel);
    for(int i=0;i<20;i++)
         panel.add(new JLabel(i.toString()));
    label.add(scroll);
    frame.add(label);

so I got the JScrollPane working properly but the JPanel has covered the background image

what should I do ?

Here's the result to adding JLabels to label:

enter image description here

The result after adding them to the scroll:

enter image description here

And after adding setOpaque(false) to the JPanel:

enter image description here


Solution

  • You can add the image as part of the JPanel's paintComponent() method, then add the labels above it, then put that pane inside a JScrollPane and finally add it to the JFrame, for example:

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    import javax.swing.BoxLayout;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    import javax.swing.SwingUtilities;
    
    public class PanelWithBackgroundImage {
        
        private JFrame frame;
        private JPanel pane;
        private Image img;
        private JScrollPane scroll;
        
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                
                @Override
                public void run() {
                    new PanelWithBackgroundImage().createAndShowGui();
                }
            });
        }
        
        public void createAndShowGui() {
            frame = new JFrame("JFrame with bg example");
            try {
                img = ImageIO.read(new FileInputStream("/home/jesus/Pictures/tokyo.jpg"));
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            pane = new JPanel() {
                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
                }
            };
            
            pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS));
            
            for (int i = 0; i < 20; i++) {
                pane.add(new JLabel("label " + i));
            }
            
            scroll = new JScrollPane(pane);
            
            frame.add(scroll);
            frame.setSize(frame.getPreferredSize());
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    }
    

    Which gives the following output:

    enter image description hereenter image description here

    If you want the JLabels centered, you can change the for loop with:

    for (int i = 0; i < 20; i++) {
        JLabel label = new JLabel("label " + i);
        label.setAlignmentX(Component.CENTER_ALIGNMENT);
        pane.add(label);
    }
    

    Which should look similar to this:

    enter image description here


    Note:

    You can copy-paste the code above, it should work, just change the image path, and that code, is called a Minimal, Complete and Verifiable Example (MCVE), next time, please post one which demonstrates what you have tried, not only parts of it, this way you'll get more, better and faster answers. Help us to help you! :)