我正在创建一个 (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
嵌套在另一个JPanel
或JComponent
调用父亲
JPanel#removeAll()
添加一个新的
JPanel
或JComponent
到父亲JPanel
之后,调用父级
JPanel#revalidate()
和JPanel#repaint()
关于java - 删除使用复杂布局的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10834600/