web-dev-qa-db-ja.com

JFrame内のJPanelをその場で変更するにはどうすればよいですか?

簡単に言うと、単純なJava Swingアプリは、JFrameにいくつかのコンポーネントが含まれています。コンポーネントの1つは、ユーザーアクションで別のJPanelに置き換えられるJPanelです。

それで、そのようなことをする正しい方法は何ですか?私はもう試した

panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();

しかし、これは機能しません。何を提案しますか?

40
yanchenko

あなたのユースケースは、 CardLayout に最適のようです。

カードレイアウトでは、同じ場所に複数のパネルを追加できますが、一度に1つのパネルを表示または非表示にできます。

51

1)最初のパネルの設定:

JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());

2)パネルの交換:

frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());

SwingUtilities.invokeLater または SwingWorker を使用するには、イベントのスレッドでこれを行う必要があることに注意してください。

25
Telcontar
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.

Java「値による参照のコピー」引数渡しを使用します。したがって、変数を変更しても、他のメソッドに渡される参照のコピーは変更されません。

また、JFrameはユーザビリティの名前で非常に紛らわしいことに注意してください。コンポーネントの追加またはレイアウトの設定(通常)は、コンテンツペインで操作を実行します。奇妙なことに、レイアウトを取得すると、実際にフレームのレイアウトマネージャーが表示されます。

18

このコードがJFrame内でjPanelを変更するアイデアを提供してくれることを願っています。

public class PanelTest extends JFrame {

        Container contentPane;

        public PanelTest()  {
           super("Changing JPanel inside a JFrame");
           contentPane=getContentPane();
        }

        public void createChangePanel() {
           contentPane.removeAll();
           JPanel newPanel=new JPanel();
           contentPane.add(newPanel);
           System.out.println("new panel created");//for debugging purposes
           validate();
           setVisible(true);
        }
}
6
Manoj Fernando

ユーザーアクションで:

//次の行に沿って何かをする必要があります

myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()

myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()

その後、必要に応じてウィンドウのサイズを変更できます。

5
ShawnD

それはすべて、その使用方法に依存します。これら2つのパネル間を行き来する場合は、CardLayoutを使用します。 1回目から2回目に1回だけ切り替えて(戻らない)場合は、 telcontar sの提案を使用して、単にそれを置き換えます。 JPanelがフレーム内の唯一のものではない場合、removeAllではなく remove(Java.awt.Component) を使用します。

これら2つのケースの中間にいる場合は、基本的に時間と空間のトレードオフです。 CardLayoutは時間を節約しますが、この他のパネル全体を常にメモリに保持する必要があるため、より多くのメモリを使用します。ただし、必要に応じてパネルを交換し、必要に応じてパネルを構築するだけであれば、その理論を維持する必要はありませんが、切り替えるのに時間がかかります。

また、代わりにタブを使用するJTabbedPaneを試すことができます(表示/非表示を自動的に処理するため、CardLayoutよりも簡単です)

3
luke

問題:コンテナにコンポーネントを追加した後、コンポーネントが表示されません。

コンテナで revalidate および repaint追加後を呼び出す必要があります表示される前に

ソース: http://docs.Oracle.com/javase/tutorial/uiswing/layout/problems.html

1
Arthur Ronald

Layout.replace()回答は、GroupLayout Managerでのみ存在/動作します。

他のLayoutManager(CardLayout、BoxLayoutなど)はこの機能をサポートしていませんが、最初にRemoveLayoutComponent(を、次にAddLayoutComponent(を再び元に戻す必要があります。:-) [レコードをそのまま設定する]

1
Warren K

私はまったく同じ問題を抱えていました!!インクレディブル!!私が見つけた解決策は:

  1. すべてのコンポーネント(JPanels)をコンテナに追加します。
  2. それらすべてにsetVisible(false)メソッドを使用します。
  3. ユーザーアクションで、setVisible(true)を表示したいパネルに設定します。
// Hiding all components (JPanels) added to a container (ex: another JPanel)
for (Component component : this.container.getComponents()) {
      component.setVisible(false);
}
// Showing only the selected JPanel, the one user wants to see
panel.setVisible(true);

Revalidate()、validate()、CardLayoutは必要ありません。

1
Gabriel

他の個人が質問に答えました。コンテンツを置き換える代わりに、JTabbedPaneを使用することをお勧めします。一般的なルールとして、アプリケーションの視覚的な要素が消えたり、他のコンテンツに置き換えられたりするのは良くありません。確かにすべてのルールには例外があり、あなたとあなたのユーザーコミュニティだけが最良のアプローチを決定できます。

1
James A Wilson
class Frame1 extends javax.swing.JFrame {

    remove(previouspanel); //or getContentPane().removeAll();

    add(newpanel); //or setContentPane(newpanel);

    invalidate(); validate(); // or ((JComponent) getContentPane()).revalidate();

    repaint(); //DO NOT FORGET REPAINT

}

再検証を使用せずに作業を実行できる場合と、再描画を使用せずに作業を実行できる場合があります。両方を使用することをお勧めします。

ContentPaneを設定した後、メソッドpack()を呼び出すだけです(Java 1.7、多分古い)このように:

JFrame frame = new JFrame();  
JPanel panel1 = new JPanel(); 
JPanel panel2 = new JPanel(); 
....
frame.setContentPane(panel1);
frame.pack();
...

frame.setContentPane(panel2);
frame.pack();
...
0
Dudu

フレームの作成時に両方のパネルを追加し、両方でsetVisible(true/false)を呼び出して表示パネルを変更することをお勧めします。 setVisibleを呼び出すと、親に通知され、再描画するように要求されます。

0
Riduidel