1

ユーザーがツリーから選択可能ないくつかの異なるビューにアクセスできる(j)アプレットを作成しています。アプレットには、現在のビューがスクロールペイン内に表示されるメイン領域があり、以前にあったものが置き換えられます。ほとんどの場合、これは正常に機能しますが、ネストされていない大きな(〜100コンポーネント)のように、置き換えられるビューのレイアウトがより複雑な場合、削除には数秒かかります。大きなビューの作成は非常に速く、削除だけが遅いです。これはアプレットでのみ顕著であり、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;
    }
}
4

3 に答える 3

2
  • add / removeすでに表示されているものには何もしないでください(setViewportView(Component)JScrollPaneを呼び出してみることができますが、そうすることはお勧めしません)

  • 父親をJPanel入れ子にする別JPanelのsまたはJComponents

  • 父に電話するJPanel#removeAll()

  • 父親に 新しいJPanelsまたはsを追加するJComponentJPanel

  • その後、父親に電話をかけJPanel#revalidate()JPanel#repaint()

于 2012-05-31T13:33:51.673 に答える
1

別の戦略:を使用しCardLayoutます。

さまざまなビューのすべてをメモリに保持したくない。

なんで?一般的なメモリでは、数百のコンポーネントを含む数百のカードを保存できます。

それらを怠惰に作成すると、GUIは通常の使用で20〜40枚のカードしか持たない可能性があります。もちろん、既存のカードを一般的なタスクに再利用し、コンテンツを変更するだけです。

于 2012-06-01T09:24:28.160 に答える
0

一般に、多くの子を持つコンポーネントの「removeAll」の呼び出し(たとえば、多くの行を持つGridBagLayoutを考えてください)は、Swingが多くの通知イベントを発生させ、同期されたセクション(java.awt.Component)を数回呼び出すため、非常に遅くなる可能性があります。 getTreeLock())。

非常に役立つヒントは、removeAllを呼び出す前にコンポーネントの表示をオフにして、再度オンにすることです。

   mypanel.setVisible(false);
   mypanel.removeAll();  //<-- it can be very slow!!!
   mypanel.setVisible(true);

表示されていないコンポーネントの削除は非常に高速です。

于 2014-09-23T09:26:40.590 に答える