简体   繁体   中英

Add JPanel to contentPane within actionListener

I'm trying to add a JPanel to my JFrame within an actionListener method, but it appears only after the second click on the button. This is a portion of my code where panCours is a JPanel and ConstituerData the targeted JFrame :

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

I don't understand why it doesn't appear as soon as I click on the button. Any explanation and help about how to fix this ?

You'll need to add a call to repaint(); (as well as probably revalidate(); ) to get the JPanel to show immediately. A basic example demonstrating your problem (and the solution) below;

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

    }
}

The above said, (as suggested by others) it's only right that I recommend against the use of a null layout in future. The swing layouts are a little awkward to begin with, but they will help you a great deal in the long run.

the answer can be found in the following snippet: you need to revalidate() the contentPane, not repaint the frame. you can add any panel you want to the contentpane like this. if you declare contentPane as a private field you dont need your getContentPane() call. contentPane is global so it can be reffered to directly from anywhere within the class. be careful about NullPointerExeptions which can be thrown if you refer to it before initialising.

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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