【问题标题】:Updating JPanel from external class will just add another one but dont replace it从外部类更新 JPanel 只会添加另一个,但不会替换它
【发布时间】:2015-04-05 09:28:00
【问题描述】:

我的主 Java 程序 (MyFrame) 应该使用由其他类 (MyPanel) 启动的其他 JPanel 更新其 JFrame 中的现有 ContentPanel,具体取决于单击的 JMenuItem 并且将传递新 JPanel 的参数。当我单击 JMenuItem 时,JPanel 不会更新,它在第一个后面而不是在前台,直到我调整窗口大小。请问你能帮我解决这个问题吗?

import javax.swing.*;
import java.awt.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

public class MyFrame extends JFrame { 

private Container contentContainer;

    public static void main(String[] args) {

        new MyFrame();

    }

    public MyFrame() {

        setTitle("MyFrame");
        setSize(300, 200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setJMenuBar(createMenu());

        MyPanel panel = makePanel(new String("Test oO"));

        contentContainer = this.getContentPane();
        setVisible(true);

    }

    public JMenuBar createMenu() {

        JMenuBar menuBar = new JMenuBar();

        JMenu menu = new JMenu("Menu");       

        JMenuItem menuItem = new JMenuItem("Test");
        menuItem.setMnemonic(KeyEvent.VK_E);
        menuItem.setToolTipText("Test");

        menuItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {                

                MyPanel dynamicPanel = makePanel(new String("Test"));
                contentContainer.add(dynamicPanel);
                contentContainer.revalidate(); 
                contentContainer.repaint();

            }

        });

        menu.add(menuItem);

        JMenuItem menuItem1 = new JMenuItem("Test 1");
        menuItem1.setMnemonic(KeyEvent.VK_E);
        menuItem1.setToolTipText("Test 1");

        menuItem1.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {

                MyPanel dynamicPanel1 = makePanel(new String("Test 1"));
                contentContainer.add(dynamicPanel1);
                revalidate(); 
                repaint();

            }

        });

        menu.add(menuItem1);


        JMenuItem menuItem2 = new JMenuItem("Dialog");
        menuItem2.setMnemonic(KeyEvent.VK_E);
        menuItem2.setToolTipText("Dialog");

        menuItem2.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent event) {

                makeDialog(new String("Zur Info"), new String("Du hast Edit geklickt"));

            }

        });

        menu.add(menuItem2);


        menuBar.add(menu);

        return menuBar;

    }

    public JDialog makeDialog(String title, String content) {

        JDialog meinJDialog = new JDialog();
        meinJDialog.setTitle(title);
        JTextArea contentArea = new JTextArea(content);
        contentArea.setEditable(false);
        meinJDialog.add(contentArea);
        meinJDialog.setSize(200,200);
        meinJDialog.setModal(true);
        meinJDialog.setLocationRelativeTo(null);
        meinJDialog.setVisible(true);
        return meinJDialog;   

    }  

    public MyPanel makePanel(String config) {

        MyPanel panel = new MyPanel(config);
        panel.revalidate(); 
        panel.repaint();
        return panel;

    }  

}

class MyPanel extends JPanel {

    public MyPanel(String config) {

        JButton testButton = new JButton(config);
        add(testButton);
        setVisible(true);
        revalidate(); 
        repaint();
        return;

    }

}

【问题讨论】:

  • 添加重新验证();重绘();添加新面板后
  • 很抱歉,但这没有任何效果,新添加的面板仍在第一个面板的后面。请编译我的示例,运行它并调整框架的大小。你会看到它会被添加到背景中。
  • 问题是您仍然拥有以前的面板。那么你在中心位置有多个面板,BorderLayout 只能处理一个。您需要在添加新的之前将其删除(然后重新验证+重新绘制)。 contentContainer.remove(0) 可以解决上面的示例。也就是说,当您考虑更换组件时,CardLayout 通常是更好的选择。

标签: java swing


【解决方案1】:

当我添加removeAll 调用时,它似乎可以工作。

import javax.swing.*;
import java.awt.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MyFrame extends JFrame {

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        new MyFrame();
      }
    });
  }

  private final Container contentContainer;

  public MyFrame() {

    setTitle("MyFrame");
    setSize(300, 200);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    setJMenuBar(createMenu());
    contentContainer = getContentPane();
    contentContainer.add(new MyPanel("Test oO"));

    setVisible(true);
  }

  public JMenuBar createMenu() {

    JMenuBar menuBar = new JMenuBar();

    JMenu menu = new JMenu("Menu");

    JMenuItem menuItem = new JMenuItem("Test");
    menuItem.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        MyPanel dynamicPanel = new MyPanel("Test");
        contentContainer.removeAll();
        contentContainer.add(dynamicPanel);
        contentContainer.revalidate();
        contentContainer.repaint();
      }
    });

    menu.add(menuItem);

    JMenuItem menuItem1 = new JMenuItem("Test 1");
    menuItem1.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        contentContainer.removeAll();
        contentContainer.add(new MyPanel("Test 1"));
        contentContainer.revalidate();
        contentContainer.repaint();
      }
    });
    menu.add(menuItem1);

    menuBar.add(menu);
    return menuBar;
  }

}

class MyPanel extends JPanel {

  public MyPanel(String config) {
    JButton testButton = new JButton(config);
    add(testButton);
    setVisible(true);
    revalidate();
    repaint();
  }
}
  • 我还将您的 main 方法封装在一个 EventQueue.invokeLater 调用中,以确保所有 Swing 操作都发生在 EDT 上
  • 我删除了所有与对话框相关的代码,因为不需要这些代码来演示问题。内联了一些其他方法,进一步减少代码 sn-p 的长度

如果您需要调试这样的情况,黄金提示:当您的JFrame 专注。这将打印出该组件的 Swing 层次结构。使用您的原始代码执行此操作清楚地表明内容窗格包含多个 MyPanel 实例。

【讨论】:

    猜你喜欢
    • 2017-11-02
    • 2020-06-28
    • 2014-09-29
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多