Thursday, 5 May 2016

java - 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.


Answer




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.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...