我正在创建一个(j)小程序,用户可以访问从树中选择的几个不同视图。小程序有一个主要区域,当前视图显示在滚动窗格内,替换之前的任何内容。大多数情况下,这可以正常工作,但是当要替换的视图具有更复杂的布局时,例如大型(约 100 个组件),而不是嵌套的,删除需要几秒钟!大视图的创建速度快如闪电,只是删除速度很慢。这仅在 applet 中很明显,在 JFrame 中运行应用程序仍然和我预期的一样快。我使用 GridBagLayout 作为视图。
经过一些实验,我发现如果我更换
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;
}
}