ボタンがパネル(JPanel
のインスタンス)に追加され、パネルがコンテナ(getContentPane()
によって生成されたインスタンス)に追加され、コンテナが構築によって追加される1つの例を見つけました。 JFrame
(ウィンドウ)に含まれます。
私は2つのことを試しました:
コンテナを取り除きました。より詳細には、ボタンをパネルに追加し(JPanel
のインスタンス)、次にパネルをウィンドウに追加しました(JFrame
のインスタンス)。うまくいきました。
パネルを取り除きました。より詳細には、コンテナにボタンを直接追加してから、ウィンドウ(JFrame
のインスタンス)にコンテナを追加しました。
だから、私は2つのことを理解していません。
同じことを行うために2つの競合するメカニズムがあるのはなぜですか?
コンテナをパネル(JPanel
)と組み合わせて使用する理由は何ですか? (たとえば、JPanelsにボタンを含めてから、コンテナにJPanelsを含めます)。 JPanel
にJPanel
を含めることはできますか?コンテナをコンテナに含めることはできますか?
追加:
たぶん私の質問の本質を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つの方法のいずれかが優れている(安全である)かどうかを知りたいだけです。
競合する2つのメカニズムではありません-JPanel
is aContainer
( JPanel javadocs の上部にあるクラス階層を見てください)。 JFrame.getContentPane()
は、Container
に表示するComponent
sを配置するJFrame
を返すだけです。内部的には、JPanel
を使用しています(デフォルトでは、setContentPane()
を呼び出すことでこれを変更できます)Container
の代わりにJPanel
を返す理由について-それは 実装ではなくインターフェイスにプログラムする -そのレベルで、気にする必要があるのはComponent
sを何かに追加できることだけであり、Container
はインターフェースではなくクラスです-それはまさにそれを行うために必要なインターフェースを提供します。
JFrame.add()
とJFrame.getContentPane().add()
の両方が同じことを行う理由については、JFrame.add()
はJFrame.getContentPane().add()
を呼び出すためにオーバーライドされます。これは常にそうではありませんでした-JDK 1.5より前では、JFrame.getContentPane().add()
を明示的に指定する必要があり、JFrame.add()
を呼び出すとRuntimeException
がスローされましたが、苦情、これはあなたが期待することをするためにJDK 1.5で変更されました。
良い質問。 「Swingは一般的に有用な3つのトップレベルコンテナクラスを提供しています。JFrame
、JDialog
、およびJApplet
....便宜上、addメソッドとそのバリアント、removeおよびsetLayoutはオーバーライドされ、必要に応じてcontentPaneに転送されます。 "— トップレベルコンテナの使用 =
おもしろい:jframe.setBackground(color)
は私には機能しませんが、jframe.getContentPane().setBackground(color)
は機能します。
その理由は、SwingがAWTから構築されており、ContainerがトップレベルのAWTオブジェクトであるためだと考えています。ただし、一般的にAWT(ヘビーウェイト)オブジェクトとSwing(ライトウェイト)オブジェクトを混在させたくないので、これは実際には最大の設計選択ではありません。
それを処理する最良の方法は、常にcontentPaneをJPanelにキャストすることだと思います。
JPanel contentPanel = (JPanel)aFrame.getContentPane();
この歴史と仕組みについても このリーポイント記事 で詳しく説明しています。特に注意してください:
getContentPane()
はContainer
オブジェクトを返します。これは実際には単純なContainer
オブジェクトではありませんが、実際はJPanel
です!これは、階層の結果としてContainer
です。事前に定義されたコンテンツペインを取得すると、実際にはJPanel
であることがわかりますが、JComponent
によって追加された機能を実際に利用することはできません。
そして
彼らは
JFrame
でadd()
メソッドを定義しました。これは、コンテンツペインの対応するadd()
メソッドを単に呼び出すだけです。特に、多くのレイアウトが複数のネストされたパネルを使用するため、JPanel
に直接追加することに慣れている必要があるため、この機能を今すぐ追加するのは奇妙に思えます。また、コンテンツペインでやりたいことのすべてがJFrame
の呼び出しで実行できるわけではありません。