3

Here's my code. I have no problem when showing up the previously designed frames (with panels added). I get this issue when adding panels to an empty JFrame dynamically.

package com.mytunes.controllers;

import com.mytunes.views.*;
import com.mytunes.views.panels.*;
import java.awt.BorderLayout;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.WindowConstants;


public class GUIController {
    ArrayList<JFrame> displayFrames = new ArrayList<JFrame>();

    JPanel displayPanel;
    HeaderPanel headerPanel = new HeaderPanel();
    FooterPanel footerPanel = new FooterPanel();


    public int showFrame(String frameName, Object controller){
        Class c;
        Constructor ctr;
        int lastFrame = -1;

        try {

           // call a class dynamically
           c = Class.forName("com.mytunes.views.frames." + frameName + "Frame");
           // calll a constructor of a class
           ctr = c.getConstructor(SessionController.class);
           // instantiate dynamically created class
           displayFrames.add((JFrame) ctr.newInstance(controller));

           // get the index of frame just added
           lastFrame = displayFrames.size()-1;

           displayFrames.get(lastFrame).setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
           displayFrames.get(lastFrame).pack();
           displayFrames.get(lastFrame).setLocationRelativeTo(null);

           // hide it by default. 
           displayFrames.get(displayFrames.size()-1).setVisible(false);

        } catch (InstantiationException ex) {
            Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchMethodException ex) {
            Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(GUIController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Error while loading class 'com.mytunes.view.frames." + frameName + "'" );
        }

        System.out.println(lastFrame);
        return lastFrame;

    }

    //-------------show panels --------------//
     public void showOperator(String frame, Object controller){

        // this works fine! this frame is already having Panels
        int f = showFrame(frame, controller);
        displayFrames.get(f).setVisible(true);
     }
    public void showEnterPIN(String frame, Object controller){


        int f = showFrame(frame, controller);
        displayFrames.get(f).getContentPane().add(new EnterPINPanel(), BorderLayout.CENTER);
        displayFrames.get(f).setVisible(true);

        //        Try every following ways to show the "Dynamically added" panels
        //        displayFrames.get(f).getContentPane().removeAll();
        //        displayFrames.get(f).getContentPane().invalidate();
        //        displayFrames.get(f).getContentPane().add(new EnterPINPanel(), BorderLayout.PAGE_START);
        //        displayFrames.get(f).getContentPane().validate();
        //        displayFrames.get(f).pack();
        //        displayFrames.get(f).setVisible(true);

    }

}

Appreciate if someone can spot this issue out for me. Thanks.

coder9
  • 1,571
  • 1
  • 27
  • 52

2 Answers2

6

If you add a component to a container you need to tell the container's layout managers to layout all the components they contain by calling revalidate() and then by sometimes calling repaint(); on the container. So, something like...

JPanel contentPane = (JPanel)displayFrames.get(f).getContentPane();
contentPane.add(new EnterPINPanel(), BorderLayout.CENTER);
contentPane.revalidate();
contentPane.repaint();

Having said this, your application design looks a bit different. Do you really use an ArrayList of JFrames? Most real-world applications don't use a bunch of separate windows but rather swap displays in one main window, and you can do a similar thing with Swing by using just one JFrame and swap views via a CardLayout.

Edit 2
What if you try:

  int f = showFrame(frame, controller);
  JPanel contentPane = (JPanel)displayFrames.get(f).getContentPane();
  contentPane.removeAll();
  contentPane.setLayout(new BorderLayout()); // just to be sure
  contentPane.add(headerPanel, BorderLayout.PAGE_START);
  contentPane.add(new EnterPINPanel(), BorderLayout.CENTER);
  contentPane.add(footerPanel, BorderLayout.PAGE_END);
  contentPane.revalidate(); // *** note that it's **re**validate
  contentPane.repaint();
  displayFrames.get(f).setVisible(true);

Again, if this doesn't help, then you should create and post a "Short, Self Contained, Correct (Compilable), Example" or SSCCE

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • +1 for quick reply and best-practice tip! Found it helpful for a newbie like me :) I was wanting to implement a "Go Back" button where user can see and edit previously entered textField data for ex: in an data entry form. – coder9 Sep 21 '11 at 04:23
  • 1
    That's fine, but there are better ways of implementing "go back". A simple stack comes to mind. – Hovercraft Full Of Eels Sep 21 '11 at 04:24
  • I'm still unable to add panels to a frame in that ArrayList. Works fine for non-arrayList frames. – coder9 Sep 21 '11 at 04:34
  • 2
    From [How to ask questions the smart way](http://catb.org/~esr/faqs/smart-questions.html): The most effective way to be precise about a code problem is to provide a minimal bug-demonstrating test case. What's a minimal test case? It's an illustration of the problem; just enough code to exhibit the undesirable behavior and no more. Consider creating and posting an [SSCCE](http://sscce.org). – Hovercraft Full Of Eels Sep 21 '11 at 04:39
0

This works

    JFrame contentPane = new JFrame();     
    contentPane.getContentPane().add(new EnterPINPanel(), BorderLayout.CENTER);
    contentPane.setVisible(true);

But not this

int f = <ArrayList index of last inserted Frame>
displayFrames.get(f).getContentPane().add(headerPanel, BorderLayout.PAGE_START);
displayFrames.get(f).getContentPane().add(new EnterPINPanel(), BorderLayout.CENTER);
displayFrames.get(f).getContentPane().add(footerPanel, BorderLayout.PAGE_END);
displayFrames.get(f).getContentPane().validate();
displayFrames.get(f).getContentPane().repaint();
displayFrames.get(f).setVisible(true);
coder9
  • 1,571
  • 1
  • 27
  • 52
  • 1
    Again, if you remain stuck, I have a feeling that only by your creating and posting an [SSCCE](http://SSCCE.org) can we truly be able to help you. – Hovercraft Full Of Eels Sep 21 '11 at 04:45
  • Hi Hovercraft: Thanks a lot!. I used Stacks and now it works fine! I think that was not the case before, but I assume it was a casting issue. I got it working by creating local JFrame references and assigning them object returned by newInstance(...). ie "JFrame ff = (JFrame) ctr.newInstance(controller);" – coder9 Sep 21 '11 at 04:58
  • please reads http://stackoverflow.com/questions/6988317/dynamically-add-components-to-a-jdialog/6989230#6989230, for LayoutManager as BorderLayout (only one JComponent can occupated concrete area) is validate with expected output to the GUI, but better would be using revalidate() @HFOE+1 – mKorbel Sep 21 '11 at 06:34