java - 删除使用复杂布局的容器

标签 java swing applet gridbaglayout

我正在创建一个 (j)applet,用户可以在其中访问可从树中选择的多个不同 View 。该小程序有一个主区域,当前 View 显示在滚动 Pane 内,替换了之前的 View 。大多数时候这工作正常,但是当要替换的 View 具有更复杂的布局时,如大型(~100 个组件),没有嵌套,删除需要几秒钟!大 View 的创建快如闪电,只有删除很慢。这仅在小程序中很明显,在 JFrame 中运行应用程序仍然和我预期的一样快。我将 GridBagLayout 用于 View 。

经过一些实验,我发现如果我替换

contents.remove(view); //contents is the view of the scrollpane.

view.removeAll();
contents.remove(view);

那么整个过程就非常快了。

我的猜测是,造成这种行为的原因是 Java 的一些布局“魔法”,虽然我有一个解决方案,但感觉不对,而且似乎表明我没有完全理解发生了什么。所以我的问题是:
有人知道实际发生了什么吗?是否有更好(更清晰)的方法来完成同样的事情?

编辑:SSCCE:http://pastebin.com/VC1T7zGv

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class SSCCE extends JApplet {
    private boolean state;

    public void init() {
        super.init();
        getContentPane().add(setupSwitchPanel(), BorderLayout.NORTH);
        getContentPane().add(setupSimplePanel(), BorderLayout.CENTER);
    }

    private JPanel setupSwitchPanel() {
        JPanel switchPanel = new JPanel();
        switchPanel.add(new JButton(new AbstractAction("Switch panels (slow)") {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                switchComponents();
            }
        }));

        switchPanel.add(new JButton(new AbstractAction("Switch panels (fast)") {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                ((JPanel)getContentPane().getComponent(1)).removeAll();
                switchComponents();
            }
        }));
        return switchPanel;
    }

    private void switchComponents() {
        getContentPane().remove(1);
        if (state)
            getContentPane().add(setupSimplePanel(), BorderLayout.CENTER);
        else
            getContentPane().add(setupComplexPanel(), BorderLayout.CENTER);
        state = !state;
        getContentPane().validate();
    }

    private JPanel setupComplexPanel() {
        JPanel contents = new JPanel();
        contents.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        for (int x = 0; x<10; x++) {
            c.gridx = x;
            for (int y = 0; y<10; y++) {
                c.gridy = y;
                contents.add(new JLabel(x + ", " + y), c);
            }
        }
        return contents;
    }

    private JPanel setupSimplePanel() {
        JPanel contents = new JPanel();
        contents.add(new JLabel("Simple view"));
        return contents;
    }
}

最佳答案

  • 不要向已经可见的 JScrollPane 添加/删除 某些内容,(当然你可以尝试调用 setViewportView(Component) ,但我不这样做建议这样做)

  • 将父JPanel嵌套在另一个JPanelJComponent

  • 调用父亲JPanel#removeAll()

  • 添加一个新的JPanelJComponent到父亲JPanel

  • 之后,调用父级 JPanel#revalidate()JPanel#repaint()

关于java - 删除使用复杂布局的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10834600/

相关文章:

java - 设置可滚动列表的边界

java - 从浏览器小程序使用 JDBC 时为 "access denied"

java - 有什么解决方法可以让复制/粘贴在 Mac 上的 JDK 7 AWT Applet 中工作吗?

java - 使用 toString 打印链表

java - 处理路径规划中不存在路径的情况

java - 如何获取应用程序退出前读取的数据库表的最后一行行号

java - 使用 JTextPane 为选定文本应用颜色

Java 小程序 : how to simulate an url has been clicked?

java - 将 java 入口点设置为一个 JAR 中另一个 JAR 中的类

java - 当我复制两个空路径时会发生什么并且为什么它不抛出异常?