Java 如何从其父JFrame外部重新绘制JPanel?

Java 如何从其父JFrame外部重新绘制JPanel?,java,swing,Java,Swing,当填充面板的方法被其父JFrame事件调用时,我可以在面板中添加/删除元素,并重新绘制它,但我不能通过其他类的事件重新绘制它,即使它们的源已经添加到面板中,或者这就是我现在理解问题的方式 我想知道这里发生了什么,谢谢 主类 public class Principal extends JFrame implements ActionListener{ private static Principal instPrincipal = null; private SubClass subCl

当填充面板的方法被其父JFrame事件调用时,我可以在
面板中添加/删除元素,并重新绘制它,但我不能通过其他类的事件重新绘制它,即使它们的源已经添加到面板中,或者这就是我现在理解问题的方式

我想知道这里发生了什么,谢谢

主类

public class Principal extends JFrame implements ActionListener{
private static Principal instPrincipal = null;    
private SubClass subClassInst =new SubClass();
public JPanel panelPrincipal;

public static Principal getInstance() {
    if (instPrincipal != null)
        return instPrincipal ;
    else {
        instPrincipal = new Principal ();
        return instPrincipal ;
    }
}

public void actionPerformed(ActionEvent event) {
    Object source = event.getSource();
    try {
        if(source == btnSub)
        {
          subClassInst.fillPanelPrincipal();
        }
        }
     catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
     }
    }
 }
子类示例

public class SubClass implements ActionListener {

private JPanel tempPanel;
private JButton btnSave; 
private Principal instPrincipal; 

public void fillPanelPrincipal() {
    instPrincipal = Principal.getInstance();
    instPrincipal.panelPrincipal.removeAll();
    //Start adding elements..
    tempPanel = new JPanel();
    instPrincipal.panelPrincipal.add(tempPanel);
    btnSave = new JButton("Save");
    btnSave.addActionListener(this);
    tempPanel.add(btnSave);
    //End. 
    instPrincipal.panelPrincipal.repaint();
  }

public void actionPerformed(ActionEvent event) {
    instPrincipal = Principal.getInstance();
    Object source = event.getSource();
    if (source == btnSave) {
    // modify local data, Database .. ; //work but need to be repainted on panelPrincipal
    instPrincipal.panelPrincipal.repaint();//does not work
    }
   }

}
更新

public class SubClass implements ActionListener {

private JPanel tempPanel;
private JButton btnSave; 
private Principal instPrincipal; 

public void fillPanelPrincipal() {
    instPrincipal = Principal.getInstance();
    instPrincipal.panelPrincipal.removeAll();
    //Start adding elements..
    tempPanel = new JPanel();
    instPrincipal.panelPrincipal.add(tempPanel);
    btnSave = new JButton("Save");
    btnSave.addActionListener(this);
    tempPanel.add(btnSave);
    //End. 
    instPrincipal.panelPrincipal.repaint();
  }

public void actionPerformed(ActionEvent event) {
    instPrincipal = Principal.getInstance();
    Object source = event.getSource();
    if (source == btnSave) {
    // modify local data, Database .. ; //work but need to be repainted on panelPrincipal
    instPrincipal.panelPrincipal.repaint();//does not work
    }
   }

}
为了进一步澄清这个问题,我在一个
JFrame
上有一个
JPanel
,有不同的类来填充它的多个功能,我在主框架上使用
JMenuItems
调用它们的方法,这些类实现
ActionListener
,通过面板不起作用,还有我在这里尝试的方法。
我曾考虑将设计更改为使用
CardLayout
,但这非常困难。

您将主体作为静态引用调用,那么它如何知道要重新绘制的帧?您应该通过子类的构造函数传递JFrame的实例。像这样:

private SubClass subClassInst = new SubClass(this);
然后像这样创建构造函数

private JFrame parent;
public SubClass(JFrame parent) { this.parent = parent; }
你可以这样使用它

this.parent.repaint();

您不应该将您的JPanel声明为
static
@user3437460 static在这里不是问题,它只是对类的所有对象都意味着相同,对于您,我做了一个没有它的测试,但没有任何更改。谢谢。这是
公共静态JPanel panelPrincipal非常危险。实际上,您无法控制其他类如何更改此值,无法保证您引用的值实际上就是屏幕上的值。以这种方式使用是一个很好的迹象表明一个糟糕的设计。此外,基于使用
设置边界
,这表明您没有使用布局管理器,这意味着
重新验证
是毫无意义的,这可能是另一个潜在问题的指示器,考虑提供一个能证明您的问题的布局管理器。这不是一个代码转储,而是您正在做的一个示例,它突出了您所遇到的问题。这将减少混乱,提高效率responses@TiyebBellal我并不是说制作你的JPanel会神奇地让一切都运转起来,而且永远不会。我说过你不应该让你的面板是静态的,因为你不必这样做,而且你会遇到很多不希望出现的问题。我已经按照你的建议通过了JFrame参数,但这不是问题所在,谢谢。