Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPanel background image doesn't apply to a JPanel inside it

I'm working on a simple registration window that appears when the java app opens.

It's a JFrame, that has a JPanel in it, which has text fields, labels, and another panel which also contains text fields and labels. My problem is that the outside panel has a background image, but it doesn't apply to the panel inside it as seen here:

Here is the whole window code:

public void start() {

    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    frame = new JFrame("Chat");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //frame.setMaximumSize(new Dimension((int)screenSize.getWidth()-1000, (int)screenSize.getHeight()-1000));
    frame.setMinimumSize(new Dimension((int)screenSize.getWidth()/2-200,(int) screenSize.getHeight()/2));
    frame.setResizable(false);

        welcome = new LoginPanel();
        welcome.setLayout(new BoxLayout(welcome, BoxLayout.Y_AXIS));
        welcome.setBorder(BorderFactory.createEmptyBorder(50, welcome.getWidth()/2-500, 50, welcome.getWidth()/2 -500));

        //repaintThread = new Thread(new RepaintRunnable(frame, welcome));
        //repaintThread.start();


            request = new JLabel("Please fill the required fields below:");
            request.setFont(new Font("Serif", Font.BOLD, 20));
            request.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
            request.setAlignmentX(Component.CENTER_ALIGNMENT);

            userInfo = new JPanel();
            userInfo.setLayout(new BoxLayout(userInfo, BoxLayout.Y_AXIS));
            userInfo.setAlignmentX(Component.CENTER_ALIGNMENT);

                Font fieldType = new Font("Serif", Font.PLAIN, 15);

                PlainDocument doc = new PlainDocument();
                doc.setDocumentFilter(new NameDocument());

                enterFirstName = new JLabel("First name:");
                enterFirstName.setAlignmentX(Component.LEFT_ALIGNMENT);
                enterFirstName.setFont(fieldType);
                firstName = new JTextField(20);
                firstName.setMaximumSize(firstName.getPreferredSize());
                firstName.setDocument(NameDocument.getNewNameDocument(NameDocument.NO_SPACE));
                firstName.getDocument().addDocumentListener(new ChangeDocumentListener());
                firstName.addActionListener(new ConfirmListener());
                firstName.setAlignmentX(Component.LEFT_ALIGNMENT);

                enterSecName= new JLabel("Surname:");
                enterSecName.setAlignmentX(Component.LEFT_ALIGNMENT);
                enterSecName.setFont(fieldType);
                secName = new JTextField(30);
                secName.setMaximumSize(secName.getPreferredSize());
                secName.setDocument(NameDocument.getNewNameDocument(NameDocument.HAS_SPACE));
                secName.getDocument().addDocumentListener(new ChangeDocumentListener());
                secName.addActionListener(new ConfirmListener());
                secName.setAlignmentX(Component.LEFT_ALIGNMENT);

                enterNickname = new JLabel("Nickname (how other people will see you in chat):");
                enterNickname.setAlignmentX(Component.LEFT_ALIGNMENT);
                enterNickname.setFont(fieldType);
                nickname = new JTextField(30);
                nickname.setMaximumSize(nickname.getPreferredSize());
                nickname.setDocument(NameDocument.getNewNameDocument(NameDocument.NO_SPACE));
                nickname.addActionListener(new ConfirmListener());
                nickname.setAlignmentX(Component.LEFT_ALIGNMENT);

            userInfo.add(enterFirstName);
            userInfo.add(firstName);
            userInfo.add(enterSecName);
            userInfo.add(secName);
            userInfo.add(enterNickname);
            userInfo.add(nickname);

            confirm = new JButton("Submit");
            confirm.setAlignmentX(Component.CENTER_ALIGNMENT);
            confirm.setEnabled(false);
            confirm.addActionListener(new ConfirmListener());

        welcome.add(request);
        welcome.add(userInfo);
        welcome.add(new Box.Filler(new Dimension(10, 10), new Dimension(10, 10), new Dimension(10, 10)));
        welcome.add(confirm);

    frame.getContentPane().add(BorderLayout.CENTER, welcome);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

And here is the LoginPanel code(the outside JPanel):

public class LoginPanel extends JPanel {
public void paintComponent(Graphics g) {
    try {
        super.paintComponent(g);
        BufferedImage background = ImageIO.read(new File("Background.jpg"));
        g.drawImage(background, 0, 0, getWidth(), getHeight(), null);
    } catch(Exception ex) {
        ex.printStackTrace();
    }
}
}

it'll also be great if someone will give me advice on how to make this code better, since I'm beginner in Java.

like image 318
Ido Fang Bentov Avatar asked Feb 08 '23 21:02

Ido Fang Bentov


2 Answers

Remember to call setOpaque(false); on any inner JPanels (and on some other components -- though not all) that cover up your image-displaying JPanel. This will allow background images to show through. You don't have to do this with JLabels as they are see-through (non-opaque) by default, but you do with JPanels.

So for you it will be:

userInfo = new JPanel();
userInfo.setOpaque(false);

One other problem is that you should never read in images from within a paintComponent method. This method may be called often, and why re-read the image when it can and should be read in only once. And more importantly, this method should be fast as possible since slowing it down needlessly will slow down the perceived responsiveness of your program. Read the image in once, and store it in a variable that is then displayed within paintComponent.

e.g.,

public class LoginPanel extends JPanel {
    private BufferedImage background;

    public LoginPanel(BufferedImage background) {
        this.background = background;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (background != null) {
            g.drawImage(background, 0, 0, getWidth(), getHeight(), this);
        }
    }
}

Read the image in and then pass it into the constructor of your LoginPanel class.

like image 51
Hovercraft Full Of Eels Avatar answered Feb 11 '23 14:02

Hovercraft Full Of Eels


Not related to your problem but:

frame.getContentPane().add(BorderLayout.CENTER, welcome);

Since JDK 4 you don't need to use the getContentPane() method you can just use frame.add(...) and the component will be added to the content pane.

Also you are using the wrong add(...) method. You are using add(constraint, component). If you read the API for the method it will tell you to use the add(component, constraint) method.

So you could be using:

frame.add(welcome, BorderLayout.CENTER);
like image 41
camickr Avatar answered Feb 11 '23 16:02

camickr