Java JPanel背景图像不';不适用于其中的JPanel

Java JPanel背景图像不';不适用于其中的JPanel,java,image,swing,background,jpanel,Java,Image,Swing,Background,Jpanel,我正在处理一个简单的注册窗口,当java应用程序打开时会出现这个窗口 它是一个JFrame,其中有一个JPanel,它有文本字段、标签,另一个面板也包含文本字段和标签。 我的问题是外部面板有背景图像,但它不适用于内部面板,如图所示: 以下是整个窗口代码: public void start() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch

我正在处理一个简单的注册窗口,当java应用程序打开时会出现这个窗口

它是一个
JFrame
,其中有一个
JPanel
,它有文本字段、标签,另一个面板也包含文本字段和标签。 我的问题是外部面板有背景图像,但它不适用于内部面板,如图所示:

以下是整个窗口代码:

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);
}
这是LoginPanel代码(外部JPanel):


如果有人能给我一些关于如何使这段代码更好的建议,那也太好了,因为我是Java初学者。

记得调用
setOpaque(false)在任何内部JPanel(以及一些其他组件——尽管不是全部)上,这些组件掩盖了显示JPanel的图像。这将允许背景图像显示出来。您不必对JLabel执行此操作,因为默认情况下它们是透明的(非不透明的),但您可以对JPanel执行此操作

因此,对您来说,它将是:

userInfo = new JPanel();
userInfo.setOpaque(false);
另一个问题是,您不应该从paintComponent方法中读入图像。此方法可能会经常调用,为什么在可以且应该只读取一次图像的情况下重新读取图像。更重要的是,这种方法应该尽可能快,因为不必要地放慢速度会降低程序的响应速度。读取图像一次,并将其存储在一个变量中,然后显示在paintComponent中

e、 g


在中读取图像,然后将其传递给LoginPanel类的构造函数。

与问题无关,但:

frame.getContentPane().add(BorderLayout.CENTER, welcome);
由于JDK 4不需要使用
getContentPane()
方法,您只需使用
frame.add(…)
即可将组件添加到内容窗格中

另外,您使用了错误的add(…)方法。您正在使用“添加”(约束、组件)。如果您阅读该方法的API,它将告诉您使用
add(component,constraint)
方法

因此,您可以使用:

frame.add(welcome, BorderLayout.CENTER);

1)
frame.setMinimumSize(新维度((int)screenSize.getWidth()/2-200,(int)screenSize.getHeight()/2))这只是基于对所需大小的猜测。添加所有组件后,我将调用
frame.pack()frame.setMinimumSize(frame.getSize())2)
新字体(“Serif”,Font.PLAIN,15)
最好是
新字体(Font.SERIF,Font.PLAIN,15)用于编译时检查。3) 
g.drawImage(背景,0,0,getWidth(),getHeight(),null)最好是
g.drawImage(背景,0,0,getWidth(),getHeight(),this)
(使用
ImageObserver
)@andrewhompson谢谢,我真的需要更多的此类建议。这是我第一次向了解java的人展示它,再次感谢。我仍然喜欢通过
getContentPane()
添加组件的“老方法”,因为它提醒我真正添加组件的位置,并且它有助于向人们解释为什么他们试图在JFrame上使用BoxLayout不能正常工作(您必须将contentPane传递给构造函数,而不是JFrame)。但是您知道所有这些。1+(当然)对于您的深刻见解!@HovercraftFullOfEels,
这有助于向人们解释为什么他们尝试在JFrame上使用BoxLayout无法正常工作(您必须将contentPane传递到构造函数中
-这很公平。@AndrewThompson:真的,真的。提醒我,不要在这里使用
null
帮助吗?编辑:没关系,我看到您对OP的评论。该建议在
drawImage
中对
this
进行了更全面的修改。映像可能会异步加载。)(在代码语句返回后)。如果给实现
ImageObserver
的组件一个仍在加载的图像,则更多的图像加载事件将触发到图像观察者,从而导致调用
repaint()
。但是在自定义绘制时,我们需要显式添加图像观察者(组件)进入
drawImage(…)
方法调用。非常感谢,您还回答了我的另一个问题,关于如何使paintComponent()方法运行得更快,因为当我调整窗口大小时,背景图像也需要一段时间才能调整大小。
frame.getContentPane().add(BorderLayout.CENTER, welcome);
frame.add(welcome, BorderLayout.CENTER);