web-dev-qa-db-ja.com

ContentPaneとJPanelの関係は何ですか?

ボタンがパネル(JPanelのインスタンス)に追加され、パネルがコンテナ(getContentPane()によって生成されたインスタンス)に追加され、コンテナが構築によって追加される1つの例を見つけました。 JFrame(ウィンドウ)に含まれます。

私は2つのことを試しました:

  1. コンテナを取り除きました。より詳細には、ボタンをパネルに追加し(JPanelのインスタンス)、次にパネルをウィンドウに追加しました(JFrameのインスタンス)。うまくいきました。

  2. パネルを取り除きました。より詳細には、コンテナにボタンを直接追加してから、ウィンドウ(JFrameのインスタンス)にコンテナを追加しました。

だから、私は2つのことを理解していません。

  1. 同じことを行うために2つの競合するメカニズムがあるのはなぜですか?

  2. コンテナをパネル(JPanel)と組み合わせて使用​​する理由は何ですか? (たとえば、JPanelsにボタンを含めてから、コンテナにJPanelsを含めます)。 JPanelJPanelを含めることはできますか?コンテナをコンテナに含めることはできますか?

追加:

たぶん私の質問の本質を1行のコードに入れることができます:

_frame.getContentPane().add(panel);
_

間にgetContentPane()を入れるとどうなりますか? frame.add(panel);を試してみたところ、うまくいきました。

追加2:

意味を明確にするために、いくつかのコードを追加したいと思います。この例では、JPaneのみを使用しています。

_import Java.awt.*;
import javax.swing.*;
public class HelloWorldSwing {
    public static void main(String[] args) {
        JFrame frame = new JFrame("HelloWorldSwing");
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());        
        panel.add(new JButton("W"), BorderLayout.NORTH);
        panel.add(new JButton("E"), BorderLayout.SOUTH);
        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}
_

この例では、コンテンツペインのみを使用します。

_import Java.awt.*;
import javax.swing.*;
public class HelloWorldSwing {
    public static void main(String[] args) {
    JFrame frame = new JFrame("HelloWorldSwing");
    Container pane = frame.getContentPane();
    pane.setLayout(new BorderLayout()); 
    pane.add(new JButton("W"), BorderLayout.NORTH);
    pane.add(new JButton("E"), BorderLayout.SOUTH);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
    }
}
_

両方ともうまくいきます!私はただ、物事を行うためのこれらの2つの方法のいずれかが優れている(安全である)かどうかを知りたいだけです。

31
Roman

競合する2つのメカニズムではありません-JPanelis aContainerJPanel javadocs の上部にあるクラス階層を見てください)。 JFrame.getContentPane()は、Containerに表示するComponentsを配置するJFrameを返すだけです。内部的には、JPanelを使用しています(デフォルトでは、setContentPane()を呼び出すことでこれを変更できます)Containerの代わりにJPanelを返す理由について-それは 実装ではなくインターフェイスにプログラムする -そのレベルで、気にする必要があるのはComponentsを何かに追加できることだけであり、Containerはインターフェースではなくクラスです-それはまさにそれを行うために必要なインターフェースを提供します。

JFrame.add()JFrame.getContentPane().add()の両方が同じことを行う理由については、JFrame.add()JFrame.getContentPane().add()を呼び出すためにオーバーライドされます。これは常にそうではありませんでした-JDK 1.5より前では、JFrame.getContentPane().add()を明示的に指定する必要があり、JFrame.add()を呼び出すとRuntimeExceptionがスローされましたが、苦情、これはあなたが期待することをするためにJDK 1.5で変更されました。

29
Nate

良い質問。 「Swingは一般的に有用な3つのトップレベルコンテナクラスを提供しています。JFrameJDialog、およびJApplet....便宜上、addメソッドとそのバリアント、removeおよびsetLayoutはオーバーライドされ、必要に応じてcontentPaneに転送されます。 "— トップレベルコンテナの使用 =

3
trashgod

おもしろい:jframe.setBackground(color)は私には機能しませんが、jframe.getContentPane().setBackground(color)は機能します。

1
DanPB

それはすべて最後のバージョンで書かれています API doc JFrame.add()(今日)で十分です。

以前のJavaバージョン ここ と比較できます。

1
PeterMmm

その理由は、SwingがAWTから構築されており、ContainerがトップレベルのAWTオブジェクトであるためだと考えています。ただし、一般的にAWT(ヘビーウェイト)オブジェクトとSwing(ライトウェイト)オブジェクトを混在させたくないので、これは実際には最大の設計選択ではありません。

それを処理する最良の方法は、常にcontentPaneをJPanelにキャストすることだと思います。

JPanel contentPanel = (JPanel)aFrame.getContentPane();
1
Zachary Wright

この歴史と仕組みについても このリーポイント記事 で詳しく説明しています。特に注意してください:

getContentPane()Containerオブジェクトを返します。これは実際には単純なContainerオブジェクトではありませんが、実際はJPanelです!これは、階層の結果としてContainerです。事前に定義されたコンテンツペインを取得すると、実際にはJPanelであることがわかりますが、JComponentによって追加された機能を実際に利用することはできません。

そして

彼らはJFrameadd()メソッドを定義しました。これは、コンテンツペインの対応するadd()メソッドを単に呼び出すだけです。特に、多くのレイアウトが複数のネストされたパネルを使用するため、JPanelに直接追加することに慣れている必要があるため、この機能を今すぐ追加するのは奇妙に思えます。また、コンテンツペインでやりたいことのすべてがJFrameの呼び出しで実行できるわけではありません。

1
Pops