2

変数のあるフレームがあり、その変数をJPanelに追加しました。同じ変数を別のJPanelに追加したい場合は、最初のJPanelから消えます。私の問題について論理的な説明が欲しいのですが、ありがとうございます!JLabelを両方のjpanelに保存したいと思います。

public class Gui {
    JPanel panel1, panel2;
    JLabel text = new JLabel("some text");
    JFrame frame = new JFrame();

    public Gui {
        panel1 = new JPanel();
        panel1.setLayout(null);
        panel1.add(text);
        panel1.getComponent(0).setBounds(50,50,50,50);
        panel1.setBorder(BorderFactory.createLineBorder(Color.black));
        panel1.setBounds(x,y,w,h);
        // it`s working, the labels it`s visible

        panel2 = new JPanel();
        panel2.setLayout(null);
        panel2.add(text);
        panel2.getComponent(0).setBounds(100,100,50,50);
        panel2.setBorder(BorderFactory.createLineBorder(Color.black));
        panel2.setBounds(x,y,w,h);
        //it`s not working, the label ins`t visible ...

        frame.add(panel1);
        frame.add(panel2);
    }
}
4

3 に答える 3

3

免責事項: OPからのコメントに応じて回答を編集しています。しかし、質問の詳細のいくつかについてはまだ完全にはわかりません。より多くの説明が与えられるので、私は喜んで私の答えを編集します。

回答:考えられる解決策の1つは、使用しているSwingコンポーネントのサブクラスを作成することです。例えば、

public class MyPanel extends JPanel {
  private JLabel label = new JLabel("some text");

  public MyPanel() {
    this.add(label);
  }
}

MyPanelこれで、それぞれが独自のJLabelを持つ複数のインスタンスを作成できます。次に、これらのパネルをフレームに追加できます。

追加:コメントに記載されている追加情報を使用して、さらに一歩進んでカスタムJFrameクラスを作成します。

public class MyFrame extends JFrame {
  private MyPanel panel = new MyPanel();

  public MyFrame() {
    this.add(panel);
  }
}

これで、のいくつかのインスタンスを作成できますMyFrame。さらに詳しく知りたい場合は、これらのカスタムクラスの両方のコンストラクターにパラメーターを追加してJLabel、各インスタンスでテキストを異なる値に設定できますMyFrame。詳細は演習として読者にお任せします。(もちろん、行き詰まっていないか聞いてください。)

于 2012-07-23T20:48:04.940 に答える
3

他の投稿で議論されているように。すべての Swing UI コンポーネント (つまり、JLabel を含む) は、1 つの親 (つまり、JPanel) しか持つことができません。別のパネルに追加すると、以前の親から削除されます。この動作には十分な理由があります。たとえば、JPanel 1 は JPanel 2 と同じレイアウトを使用しない可能性があるため、ラベルは各 JPanel 内で 2 つの異なる配置をサポートする必要があります。オブジェクトをコンポーネントとして使用することの要点は、そのオブジェクト内に (フォント、親内の位置、幅、高さなど) のようなデータをカプセル化することです。2 つのビジュアル要素が必要な場合は、別の要素を作成するだけです。ここで、「これらすべてのコントロール間でデータを同期するにはどうすればよいですか?」という問題が生じます。それは基本的に、自分のプログラムに適した Swing アーキテクチャをどのように構築するのかということです。

やりたくないことは、Swing コンポーネント モデル (Jabel、JTextField など) をデータ モデルとして使用することです。そして、あなたの質問とコードを読んだ後、それがあなたがしていることだと思います。気づかないかもしれません。UI コンポーネントは表示のみに使用する必要があります。これらは、データ モデルの内容を反映しています。そのため、Swing を使用しないモデルを作成する必要があります。表示方法に関係なく、問題をモデル化する必要があります。つまり、常に Swing や Web などであると想定すべきではありません。

これには非常に実用的な理由があります。1 年後に UI を再設計したいとします。ビュー コンポーネントとデータ モデルを組み合わせた場合、最初からやり直す必要があります。テクノロジーを切り替えていなくても。JList から JTable または JTreeTable に切り替えるとします。モデルからビューを分割しないと、画面上にあるコンポーネントのタイプを単純に変更するだけで、絶対的な悪夢になる可能性があります。加えて、ビューは物事を表示しますが、モデルには、ユーザーには表示されないが、表示されているものに関連付けられている情報が必要な場合があります。たとえば、データベース内の行の ID です。ビューとデータモデルを一緒に詰め込むと、この目に見えない情報を奇妙な方法で保存するためにちょっとした工夫が必要になります。他の人が理解するのを難しくするもの。

私の意味がわからない場合は、6 か月後に最初の大規模な再設計を行う必要があるか、今すぐ痛みを和らげて、今私が意味することを理解しようとするかのどちらかです。単純な POJO だけで十分です。次に、それらの POJO を Swing コンポーネントと共有します。例えば:

MySpecialPanel panel1 = new MySpecialPanel();
MyOtherSPecialPanel panel2 = new MyOtherSpecialPanel();
frame.add( panel1 );
frame.add( panel2 );

...a little while later...

MySpecialPOJO specialPOJO = ...some call to a service...;
panel1.setSpecialPOJO( specialPOJO );
panel2.setSpecialPOJO( specialPOJO );

MySpecialPanel と MyOtherSpecialPanel という JPanel の 2 つのサブクラスを作成したことに注意してください。その中で、それらはそれらに含まれるコンポーネントを作成します。次に、MySpecialPOJO 型のデータ モデル オブジェクトを取得するセッター メソッドを公開します。これらのメソッド内には、次のようなものが表示される場合があります。

public void setSpecialPOJO( MySpecialPOJO specialPOJO ) {
   this.model = specialPOJO;
   textField1.setText( specialPOJO.getName() );
   textField2.setText( specialPOJO.getDescription() );
   radioButtonGroup.setSelected( specialPOJO.getGender() );
   ....
}

これで、モデル オブジェクトを取得し、そのビューを構成する相対的な UI コンポーネントを更新する方法ができました。他の外部依存関係 (つまり、オブジェクトの取得元) は気にしないことに注意してください。所有するコントロールを更新して、POJO によって運ばれるものを反映するだけです。これらの単純なルールに従えば、特別なパネルを簡単にインスタンス化できます。必要なインスタンスが 1 つだけか、多数のインスタンスか。また、プログラム内でパネルを移動する必要がある場合、依存関係を POJO だけに減らすと、非常に簡単に移動できます。これには他にもたくさんありますが、今のところはこれで始められます。UI からデータを取り出して POJO (イベント!) に戻す方法を理解する必要があります。コントローラー、サービスなど

これもあなたを助けるかもしれません:

最新の Swing MVC の例 + 質問

于 2012-07-23T21:18:10.733 に答える
2

You can't. As you noticed, a control can only be attached to one window at a time, and if you try to attach it to another one, it will remove itself from the first.

Suggestions:

panel2.add(text.clone()); // clone the existing label
panel2.add(new JLabel("some text")); // make a new label from scratch
于 2012-07-23T20:43:00.350 に答える