2014-03-05 75 views
1

我试图在actionListener方法中向我的JFrame添加一个JPanel,但它只在第二次点击按钮后才出现。这是我的代码的一部分,其中panCoursJPanelConstituerData目标JFrame将JPanel添加到actionListener中的contentPane

addCours.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      panCours.setBounds(215, 2, 480, 400); 
      panCours.setBorder(BorderFactory.createTitledBorder("Saisir les données concernant le cours")); 
      ConstituerData.this.getContentPane().add(panCours); 
     } 
    }); 

我不明白为什么我点击按钮不会立即出现。有关如何解决这个问题的任何解释和帮助?

+0

看看在'actionPerformed'结尾的'JFrame'上调用'pack'是否解决了你的问题。 –

+0

这个调用解决了这个问题,但创建了另一个问题:它将我的'JFrame'的每个维度都设置为0. – sk001

+0

@HoNoSousa - 他用外观来看一个空布局,所以这不会有太大的帮助。尝试在您的JFrame或JPanel上调用repaint。 –

回答

2

您需要添加对repaint();(以及可能revalidate();)的调用才能立即显示JPanel。下面是一个演示您的问题(和解决方案)的基本示例;

public class Test { 

    public static void main(String[] args) { 
     final JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLayout(null); 

     JButton button = new JButton("Test");      
     button.setBounds(20, 30, 100, 40); 
     button.addActionListener(new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       JPanel panel = new JPanel(); 
       panel.setBackground(Color.red); 
       panel.setBounds(215, 2, 480, 480); 
       frame.add(panel); 
       frame.revalidate(); // Repaint here!! Removing these calls 
       frame.repaint(); // demonstrates the problem you are having. 

      } 
     }); 

     frame.add(button); 
     frame.setSize(695, 482); 
     frame.setVisible(true);    

    } 
} 

上面说了,(其他人的建议),这是唯一正确的,我建议不要在将来使用null布局。摆动布局开始时有点尴尬,但从长远来看,它们会帮助你很多。

+3

请不要暗示人们使用'null'布局......这只是合适的坏建议,并引入更多的问题 – MadProgrammer

+0

谢谢,@RudiKershaw。如果我只有一个“JPanel”添加,现在是正确的。但我想根据按钮的选择在许多'JPanel'之间切换。使用这个解决方案,显示的'JPanel'不是与'JButton'点击相对应的那个。我能怎么做 ? – sk001

+0

@MadProgrammer - 很好,我会更新我的答案来建议布局。但一般来说,一旦有人正在进入一个项目,他们不会想要改变。建议使用布局管理器将在未来帮助他们,但现在对他们无帮助。 –

2

答案可以在下面的代码片段找到: 你需要revalidate()这个contentPane,而不是重画框架。您可以像这样将所需的任何面板添加到内容面板。如果您将contentPane声明为私有字段,则不需要您拨打getContentPane()。 contentPane是全球性的,因此可以直接从课程中的任何位置进行调整。 请注意NullPointerExeptions如果您在初始化之前提及它,可以抛出它。

public class testframe extends JFrame { 

private JPanel contentPane; 

/** 
* Launch the application. 
*/ 
public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       testframe frame = new testframe(); 
       frame.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

/** 
* Create the frame. 
*/ 
public testframe() { 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    contentPane = new JPanel(); 
    setContentPane(contentPane); 

    JButton btnNewButton = new JButton("New button"); 
    btnNewButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent arg0) { 
      JPanel a = new JPanel(); 
      contentPane.add(a); 
      contentPane.revalidate(); 
     } 
    }); 
    contentPane.add(btnNewButton); 
} 

} 
+0

http://stackoverflow.com/questions/1097366/java-swing-revalidate-vs-repaint - 要绝对安全,可能需要重新验证和重新绘制。但certinaly不*只是*重新验证。 –