web-dev-qa-db-ja.com

Java Swingレイアウトマネージャーによるフラストレーション

私は何年もの間、Swingレイアウトマネージャーをマスターしようとして成功していません。 Swingで何かをする必要があるときはいつでも、それは釘を引っ張って視覚コンポーネントを希望どおりに整列させるようなものです。私はマティスのようなフレームワークに精通していますが、それはポイントではありません。

私の質問は次のとおりです。Swingにレイアウトマネージャーが必要なのはなぜですか?複雑すぎるパラダイムのようです。私ができるようにしたいのは、単純なJFrameを実行してから、各コンポーネント(JLabelなど)に対して、配置するX座標とY座標を指定するだけです。 100%予測どおりに機能するこの単純なアプローチの何が問題になっているのか、誰かが説明できますか?それともこれとまったく同じことをする実際のレイアウトマネージャーはありますか?

3
amphibient

私ができるようにしたいのは、単純なJFrameを実行してから、各コンポーネント(JLabelなど)に対して、配置するX座標とY座標を指定するだけです。

nullレイアウトでそれを行うことができます:

jPanel.setLayout(null);
jLabel.setBounds(5, 5, 200, 300);
jPanel.add(jLabel);
jFrame.add(jPanel);
6
m3th0dman

レイアウトマネージャーを使わないプログラミングのほうが一般的だった時期を覚えていられないかもしれません。別の画面解像度を使用している人と実際にアプリケーションを共有する必要がなければ、1つのサイズで画面を修正する必要がありました。または、見栄えの悪いスケーリングに対処する必要がありました。

問題の一部は、「自然な」および「明白な」スケーリングが実際には非常に複雑であると考える可能性があることです。テキスト領域などの一部のコンポーネントは、当然両方向にサイズ変更できますが、見た目はかなり良いです。コンボボックスなどの一部のコンポーネントは、水平方向に拡大縮小した場合にのみ正常に見え、ボタンなどの一部のコンポーネントは、どちらかの方向に少し拡大した場合に自然に表示されることはまれです。レイアウトマネージャーを使用すると、コンポーネントを組み合わせて、スケーリングを自然に見せることができます。

18
Karl Bielefeldt

他のツールキットにも同等の概念があります(たとえば、Tkにはジオメトリマネージャーがあります)。これらのツールキットは、1つの正確なサイズに固定されていないGUIを持つことの絶対的な中心となります。次の場合に問題になります。

  1. アクセシビリティの理由でサイズが変わる可能性のあるフォント、または
  2. 画面のサイズが異なる、または
  3. サイズ変更可能なウィンドウ、または
  4. 一部のコンポーネントには可変量のコンテンツがあります。

これは、アダプティブサイジングが必要な理由の完全なリストではありませんが、必要な場合でも、物事の正確な配置とサイジングを制御できない場合があることを示しています。ピクセルレベルで物事を制御しようとするのをやめ、代わりに、コンピューターがあなたに説明するより一般的な規則に従ってそれを管理するようにさせる方がはるかに良いです。レイアウトマネージャが行うことは、これらのルールを適用することです。

FWIW、良いレイアウトマネージャーを書くのは難しいです。とても大変。実際、私が知っているものは、私の経験で最高のレイアウトを提供します(Tkのグリッドマネージャーは、サックがないことを除き、GridBagManagerの一種です)内部的に複雑な連立方程式ソルバーであり、ユーザーの指示が解決策を与えないときでさえ、答えは飛び出します。また、開発には数年の労力が注がれているので(本当に!)、簡単に再現できるとは思えません。レイアウトマネージャーをうまく機能させることは一般的に難しいため、それらを書くほとんどの人は、実際には特にスマートな仕事を行わない非常に具体的なものを書く傾向がありますが、実装は十分に単純であり、少なくとも単純なケースを処理するのは簡単です彼らは実際に気にしています。

9
Donal Fellows

MigLayout の使用を検討してください。これは、私が問題を抱えたことのない包括的なレイアウトマネージャです。何が可能で、どれほど簡単に使用できるかを最初に理解するには、ホームページからリンクされているサンプルアプリケーションをご覧ください。ウィンドウのサイズを変更して、ユーザーインターフェイスが画面のサイズにどのように適応できるかを確認してください。

レイアウトマネージャーの背後にある主な理由は、ユーザーのニーズやニーズに合わせてアプリケーションをエレガントに拡張できるようにすることです。 MigLayoutは、簡単に調整できる膨大な数の制約とルールを提供することでこれを容易にします。その一部は、一部の領域でHTML + CSSよりも強力になります(ただし、最終的には変わります)。また、何をしようとしているのかを正確に示すデバッグモードがあり、ユーザーのオペレーティングシステムに応じてボタンを配置する機能があります。

絶対配置のいくつかの例:

// adds item at 100, 100
panel.add(item, "pos 100, 100");
// adds item 10% + 5 "logical pixels" + 1 inch from left side of parent
// and centers itself 75% of the way down parent component
panel.add(item, "pos (10% + 5lp + 1in) .75al"); 

詳細は、メインページからリンクされているチュートリアル、サンプルアプリケーション、およびチートシートにあります。

5
deterb

さて、Swingはクロスプラットフォームであるため、レイアウトマネージャーが必要であり、異なるプラットフォームで異なるサイズのコンポーネントをレンダリングします。数式ルールを使用して要素を線で描画することで、移植性が大幅に向上します。

ちなみに、流動性を維持したまま配置を適切に制御したい場合は、GroupLayoutを確認できます。それは完璧ではありませんが、それはあなたに比較的細かい制御を与えます、そして私はそれを非常に頻繁に使用します

これが非常に複雑に見える理由は、参照する動作が標準JavaのGridBagLayoutマネージャーによって実装されているためだと思います。 GridBagLayoutは非常に表現力豊かですが、気にしないかもしれないx、y座標に加えて、多数のパラメーターも含みます(たとえば、複数のセルにまたがるコンポーネント、さまざまな方法でのアンカー/塗りつぶしなど)。

これらのオプションを使用すると、ドキュメントが少し厄介になる可能性がありますが、必要になるまでこれらの追加のパラメーターを無視してかまいません。ここに私があなたが求めたものとあまり変わらない典型的な使用パターンがあります:

setLayout(new GridBagLayout());

// Implicit location = 0,0
// We need to set the weight to be non-zero otherwise everything 
// will clump together in the middle of the frame. Apart from that, 
// we can just provide x,y coords
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx=1;
gbc.weighty=1;

add(myButton, gbc);

// Now add something at 1,0
gbc.gridx = 1;
add(myLabel, gbc);

// Now add something at 2,0
gbc.gridx = 2;
add(myOtherLabel, gbc);

// Now add something at 1,0, it should span the full width and
// it should be anchored to the bottom of the frame
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.SOUTH;

add(myOtherComponent, gbc);

0,1の項目からわかるように、多くの制約を設定できますが、(必要する必要はありません。気になるものを指定するだけです。

1
PhilDin

画面にはさまざまなサイズがあるため、すでに説明したように、layoutManagers。

すでに述べたように、私は TableLayout を使用することをお勧めします

私の画面のほとんどはかなりシンプルです。Swingの独自のフロントエンドを使用して、次のようなシンプルな画面を定義できます。

pnl.addLine("Record Name", sfRecordName);
pnl.addLine("Description", sfDescription)
       .setHeight(DESCRIPTION_HEIGHT);
pnl.addLine("Record Type", sfRecordType);
pnl.addLine("System",      sfSystem)
       .setGap(BasePanel.GAP0);
pnl.addLine("List",        sfList);

addLineメソッドは、舞台裏でtableLayoutを使用して画面をレイアウトします。

  • オプションで、フィールドの名前を(プロンプトに)設定します。これは、一部のSwingテストツール(たとえば、初期バージョンのMarathon)で役立ちます。
  • 言語変換を行う

周りを見てください、利用可能なさまざまなSwingフロントエンドがあります

0
Bruce Martin

配置したい場所のX座標とY座標を指定するだけです

はい、ウィンドウのサイズを変更しても、JLabelとテキストエディターのサイズは画面に基づいて調整されません。同じ位置に設定されたままになります。

カスタムレイアウトでレイアウトを再調整できますが、レイアウトマネージャーと比較してカスタムレイアウトを使用するのは困難です。

適切な layout manager を選択すると、作業が簡単になります。

ただし、レイアウトを追加すると、ラベルのサイズはレイアウトに基づいて調整されます。

0
sathya