简体   繁体   English

JPanel背景图片不适用于其中的JPanel

[英]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. 我正在开发一个简单的注册窗口,该窗口在java应用程序打开时出现。

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. 它是一个JFrame ,里面有一个JPanel ,它有文本字段,标签和另一个包含文本字段和标签的面板。 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): 这是LoginPanel代码(外部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. 如果有人会就如何改进这些代码给我建议,那也很棒,因为我是Java的初学者。

Remember to call setOpaque(false); 记得调用setOpaque(false); on any inner JPanels (and on some other components -- though not all) that cover up your image-displaying JPanel. 在任何内部JPanels(以及其他一些组件 - 虽然不是全部)上覆盖你的图像显示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. 您不必使用JLabel执行此操作,因为默认情况下它们是透视(非透明),但您使用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. 另外一个问题是,你应该从方法的paintComponent内读取的图像。 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. 一次读取图像,并将其存储在随后在paintComponent中显示的变量中。

eg, 例如,

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. 读入图像,然后将其传递给LoginPanel类的构造函数。

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. 从JDK 4开始,您不需要使用getContentPane()方法,只需使用frame.add(...) ,该组件就会被添加到内容窗格中。

Also you are using the wrong add(...) method. 你也使用了错误的add(...)方法。 You are using add(constraint, component). 您正在使用add(约束,组件)。 If you read the API for the method it will tell you to use the add(component, constraint) method. 如果您阅读该方法的API,它将告诉您使用add(component, constraint)方法。

So you could be using: 所以你可以使用:

frame.add(welcome, BorderLayout.CENTER);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM