2015-10-04 115 views
4

我工作的Java应用程序打开时会出现一个简单的登记窗口。JPanel的背景图片不适用于一个JPanel里面

这是一个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):

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(); 
    } 
} 
} 

它也将是巨大的,如果有人给我如何将T建议他的代码更好,因为我是Java初学者。

+2

1)'frame.setMinimumSize(新尺寸((INT)screenSize.getWidth()/ 2-200(INT)screenSize.getHeight()/ 2) );'这是基于对所需大小的猜测。 '2)'新的字体( “衬线”,Font.PLAIN,15;那'frame.setMinimumSize(frame.getSize())后立即'然后,添加完所有组件后,我反而叫'frame.pack() );''最​​好是'new Font(Font.SERIF,Font.PLAIN,15);'用于编译时检查。 3)'g.drawImage(背景,0,0,的getWidth(),的getHeight(),NULL);'将最好是'克。drawImage(背景,0,0,getWidth(),getHeight(),this);'(使用'ImageObserver')。 –

+0

@AndrewThompson谢谢,我真的很需要这些建议。这是我第一次将它展示给懂java的人,谢谢。 –

回答

5

记得拨打任何内部JPanels setOpaque(false);(和其他一些部件 - 尽管不是全部),涵盖了您的图像显示的JPanel。这将允许背景图像显示。您没有默认使用的JLabel要做到这一点,因为他们看透(非不透明),但你JPanels做。因此,对于你

这将是:

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

另外一个问题是,你永远不应该在图像从方法的paintComponent内读取。这种方法可能会经常被调用,为什么重新读取图像时应该只读一次。更重要的是,这种方法应该尽可能快,因为不必要地减慢它会减慢程序的感知响应速度。一次读取图像,并将其存储在一个变量中,然后显示在paintComponent中。

例如,

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); 
     } 
    } 
} 

阅读的图像,然后把它传递到您的LoginPanel类的构造函数。

+1

@AndrewThompson:的确如此。提醒我,在这里不会使用'null'帮助?编辑:没关系,我看到你对OP的评论。 –

+0

该建议重新。在OP中,'drawImage'中的'null' /'this'更加完整。图像可能异步加载(在代码语句返回后)。如果你给一个图像加载一个实现了ImageObserver的组件,因为更多的图像加载事件将被触发到图像观察器,从而导致调用repaint()。但是在自定义绘画时,我们需要明确地将图像观察者(组件)添加到'drawImage(..)'方法调用中。 –

+0

非常感谢你,你也回答了我的另一个问题,关于如何使paintComponent()方法运行得更快,因为当我调整窗口大小时,花费一些时间直到背景图像调整大小。 –

3

不相关的问题,但:

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

由于JDK 4,你不需要使用getContentPane()方法,你可以只使用frame.add(...)和组件将被添加到内容窗格中。

而且你使用的是错误的add(...)方法。您正在使用添加(约束,组件)。如果您阅读该方法的API,它会告诉您使用add(component, constraint)方法。

所以,你可以使用:

frame.add(welcome, BorderLayout.CENTER); 
+0

我仍然喜欢通过'getContentPane()'添加组件的“老方法”,因为它让我想起我真正添加组件的位置,并且在向人们解释为什么他们尝试在JFrame上使用BoxLayout的尝试不是很有帮助无法正常工作(您必须将contentPane传递给构造函数,而不是JFrame)。但你知道这一切。 1+(当然)为您的伟大见解! –

+0

@HovercraftFullOfEels,'当向人们解释为什么他们尝试在JFrame上使用BoxLayout不能正常工作(您必须将contentPane传递到构造函数中)时,它会有所帮助。 – camickr