【问题标题】:How to refresh JInternalFrame or JPanel form on button click where JPanel is a separate class and used in JInternalFrame如何在按钮单击时刷新 JInternalFrame 或 JPanel 表单,其中 JPanel 是一个单独的类并在 JInternalFrame 中使用
【发布时间】:2025-12-13 02:20:09
【问题描述】:

我正在尝试在一个 JFrame 中构建具有多个屏幕的桌面应用程序。 因此,每个按钮单击事件都会将我们带到屏幕中刷新组件的单独屏幕。到目前为止,这种方法对我有用,但我面临的问题是即使在使用“.dispose()、.repaint()、.revalidate()、.invalidate()”函数之后。 JInternalFrame 或 Jpanel 似乎没有刷新其组件。

效果类似于下面的 gif。

Tabbed Style

我知道 JtabbedPane 存在,但对于我的方法 JtabbedPane 不可行。

下面我通过复制我面临的问题来发布缩小代码。

MainMenu.Java(主类文件)

package test;

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JInternalFrame;

public class MainMenu extends JFrame {

    private JPanel contentPane;
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MainMenu frame = new MainMenu();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public MainMenu() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 841, 522);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        JPanel panel = new JPanel();
        panel.setBounds(10, 10, 807, 63);
        contentPane.add(panel);
        panel.setLayout(new GridLayout(1, 0, 0, 0));
        
        JButton Tab1 = new JButton("Tab1");
        panel.add(Tab1);
        
        JButton Tab2 = new JButton("Tab2");
        panel.add(Tab2);
        
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 88, 807, 387);
        contentPane.add(scrollPane);
        
        JInternalFrame internalFrame1 = new JInternalFrame();
        JInternalFrame internalFrame2 = new JInternalFrame();
        
        Tab1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Panel1 panel1 = new Panel1();
                if(internalFrame1 !=null) {
                    internalFrame1.dispose();
                    panel1.invalidate();
                    panel1.revalidate();
                    panel1.repaint();
                }
                internalFrame1.setTitle("Panel 1");
                scrollPane.setViewportView(internalFrame1);
                internalFrame1.getContentPane().add(panel1);
                internalFrame1.setVisible(true);
                
            }
        });
        
        Tab2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Panel2 panel2 = new Panel2();
                if(internalFrame2 !=null) {
                    internalFrame2.dispose();
                    panel2.invalidate();
                    panel2.revalidate();
                    panel2.repaint();
                }
                internalFrame2.setTitle("Panel 2");
                scrollPane.setViewportView(internalFrame2);
                internalFrame2.getContentPane().add(panel2);
                internalFrame2.setVisible(true);
            }
        });
    }
}

以及JInternal Frames所在的对应Jpanel类文件 Panel1.java

package test;

import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;

public class Panel1 extends JPanel {
    private JTextField textField;

    /**
     * Create the panel.
     */
    public Panel1() {
        setLayout(null);
        
        textField = new JTextField();
        textField.setBounds(10, 60, 430, 19);
        add(textField);
        textField.setColumns(10);
        
        JButton btnNewButton = new JButton("Example Button");
        btnNewButton.setBounds(10, 156, 430, 21);
        add(btnNewButton);

    }
}

Panel2.java

package test;

import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;

public class Panel2 extends JPanel {
    private JTextField textField;

    /**
     * Create the panel.
     */
    public Panel2() {
        setLayout(null);
        
        textField = new JTextField();
        textField.setBounds(10, 60, 430, 19);
        add(textField);
        textField.setColumns(10);
        
        JButton btnNewButton = new JButton("New button2");
        btnNewButton.setBounds(21, 157, 419, 21);
        add(btnNewButton);

    }
}

P.S:这是我第一次在 * 上提问,所以请原谅我,如果我错过了什么,请尽可能指导我

谢谢你:)

编辑: 我面临的问题是表面上看起来 Jpanel 已经被刷新,但是像 JtextField 这样的组件仍然隐藏了之前写入的文本,并且仅在我单击该 JTextField 时才显示文本

下面我附上另一个 gif 显示突出问题。我已经突出显示了我面临问题的部分。

Issue I am Facing

【问题讨论】:

  • JInternalFrame 或 Jpanel 似乎没有刷新其组件。 - 我不确定您期望发生什么。每次单击按钮时,我都会看到按钮上的标题和文本会发生变化。这意味着组件已刷新。其他问题: 1) 变量名不应以大写字符开头。 2) 不要使用空布局和 setBounds()。 Swing 旨在与布局管理器一起使用。例如,没有理由使用 JScrollPane,因为当添加到其中的组件使用空布局时它不起作用。
  • 3) revalidate() 仅在使用布局管理器时有效。 revalidate() 和 repaint() 会在您删除/添加组件后在容器上调用。
  • @camickr 感谢您在我的代码中发现的其他问题。我已经更新了我的问题并在我面临这个问题的特定部分发布。如果可能的话,请看一下并建议我可能的解决方案。如果我错过了您的 cmets 中的某些内容,我深表歉意。谢谢

标签: java swing jframe jpanel jinternalframe


【解决方案1】:

dispose() 方法不会删除组件,因此当您使用以下内容时,您会不断将组件添加到内部框架:

internalFrame1.getContentPane().add(panel1);

相反,您可能会执行以下操作:

Container contentPane = internalFrame1.getContentPane();
contentPane.removeAll();
contentPane.add( panel1 );
contentPane.revalidate();
contentPane.repaint();

【讨论】:

    【解决方案2】:

    您可以在 Jframes 中使用 JPanel,然后使用 CardLayout 更改面板(这可以像不同的屏幕一样)

    【讨论】:

    • 如果我不清楚,我很抱歉,但我发布的上述代码已经选择 Jpanels 作为单独的屏幕,我不知道我哪里出错了。但是你的建议看起来就像我已经在做的改变了 UI。