【问题标题】:Dynamically added JPanels are not showing up in SwingSwing 中未显示动态添加的 JPanel
【发布时间】:2011-09-21 03:24:48
【问题描述】:

这是我的代码。显示以前设计的框架(添加了面板)时我没有问题。将面板动态添加到空 JFrame 时出现此问题。

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

    }

}

如果有人能帮我发现这个问题,我不胜感激。谢谢。

【问题讨论】:

  • 请参阅下面我的回答中的 edit 2

标签: java swing user-interface jframe jpanel


【解决方案1】:

如果您将组件添加到容器中,您需要通过调用 revalidate() 然后有时在容器上调用 repaint(); 来告诉容器的布局管理器来布局它们包含的所有组件。所以,类似...

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

话虽如此,您的应用程序设计看起来有点不同。你真的使用 JFrame 的 ArrayList 吗?大多数实际应用程序不使用一堆单独的窗口,而是在一个主窗口中交换显示,您可以使用 Swing 执行类似的操作,仅使用一个 JFrame 并通过 CardLayout 交换视图。

编辑 2
如果你尝试怎么办:

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

同样,如果这没有帮助,那么您应该创建并发布 "Short, Self Contained, Correct (Compilable), Example" or SSCCE

【讨论】:

  • +1 以获得快速回复和最佳实践提示!发现它对像我这样的新手很有帮助:) 我想实现一个“返回”按钮,用户可以在其中查看和编辑以前输入的 textField 数据,例如:在数据输入表单中。
  • 这很好,但是有更好的方法来实现“返回”。想到一个简单的堆栈。
  • 我仍然无法将面板添加到该 ArrayList 中的框架中。适用于非 arrayList 帧。
  • 来自How to ask questions the smart way:准确了解代码问题的最有效方法是提供最小的错误演示测试用例。什么是最小测试用例?这是问题的说明;只是足够的代码来展示不良行为,仅此而已。考虑创建并发布SSCCE。
【解决方案2】:

这行得通

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

但不是这个

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

【讨论】:

  • 再一次,如果您仍然卡住,我有一种感觉,只有您创建并发布SSCCE,我们才能真正为您提供帮助。
  • 嗨,气垫船:非常感谢!我使用了 Stacks,现在它工作正常!我认为以前不是这种情况,但我认为这是一个选角问题。我通过创建本地 JFrame 引用并将其分配给 newInstance(...) 返回的对象来使其工作。即“JFrame ff = (JFrame) ctr.newInstance(controller);”
  • 请阅读 stackoverflow.com/questions/6988317/…,对于 LayoutManager,因为 BorderLayout(只有一个 JComponent 可以占用具体区域)已通过预期的 GUI 输出进行验证,但最好使用 revalidate() @HFOE+1跨度>
猜你喜欢
  • 2016-10-25
  • 1970-01-01
  • 2013-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-30
  • 1970-01-01
  • 2021-01-29
相关资源
最近更新 更多