2009-07-17 11 views
2

Javaのレイアウトにはいつも問題がありますが、コンテンツが変更されたとき、特にサイズが変更されたときに、正しくレイアウトされていないということです。その後、各コンポーネントは、それへの参照は、コンポーネント乱雑取得のJFrame、だ持っているはずなので)私は仕事にこれを取得する唯一の方法は、(lst.packを呼び出すことですJava Swingプログラムのレイアウト自体をもう一度する

package layouttest; 

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextArea; 

public class LayoutTestStart extends JFrame implements ActionListener 
{ 
    static JButton button= new JButton("Expand"); 
    static JTextArea f = new JTextArea("A medium sized text"); 
    static LayoutTestStart lst; 

    public static void main(String[] args) { 
     //Schedule a job for the event-dispatching thread: 
     //creating and showing this application's GUI. 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 

    public static void createAndShowGUI() 
    { 
     lst = new LayoutTestStart(); 
     lst.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JPanel all = new JPanel(); 

     button.addActionListener(lst); 

     all.add(button); 
     all.add(f); 
     lst.getContentPane().add(all); 

     lst.setVisible(true); 
     lst.pack(); 
    } 
    @Override 
    public void actionPerformed(ActionEvent e) 
    { 
     f.setText(f.getText()+"\n"+f.getText()); 

     // this doesn't work 
     f.invalidate(); 

     // this does but it's cheating 
//  lst.pack(); 
    } 
} 

、それは浮気だ:以下の例を見てみましょう別のクラスです。この例を有効にするにはどうすればよいでしょうか?

答えて

2

一般的に、ユーザーは入力するたびにフレームのサイズが変わるのが気に入らないのが一般的です。フレームは、成長に対応するように設計する必要があります。そのため、テキスト領域を指定した数の行と列を持つように定義します。次に、テキストエリアをスクロールペインに追加し、スクロールペインをフレームに追加します。データが変更されると、必要に応じてスクロールバーが表示されたり消えたりします。

しかし、本当に動的に変化するフレームが必要な場合は、pack()を使用する必要があります。あなたは使用することができます。

SwingUtilities.windowForComponent(...) 

コンポーネント()をパックするウィンドウを見つけるために、のActionEventのソースコンポーネントです。

+0

これまでのところ、これは私の最高の選択肢のようです – kresjer

0

まず、あなたの前提について、トップレベルの祖先(コンポーネントにそのようなメソッドがあります)を取得してパックを呼び出すことができ、packを呼び出すことができます。静的メソッドを作成し、どこからでも呼び出すことができます。それはうまくいくでしょう。

もう1つのオプション(おそらく本当に好ましいオプション)は、これを満たすレイアウトマネージャを使用することです。もちろん、GridBagLayoutはそれをすべて行いますが、それは、人間が使用することを意図していないと主張する人がいます。 MigLayoutはオープンソースのレイアウトマネージャーで、もう少し正常です。

+0

私はあなたの最初の提案に似ハッキング使用されますが、それは非常にいい感じがしません。 2番目のオプションに関しては、通常、サイズが変更されたフィールドは一連のレイアウトマネージャーに階層化されているため、すべてを正面のレイアウトマネージャーに変更する必要があります。 – kresjer

+0

私はMigLayoutを見ていて、名前以外はすばらしく見えますが、MigLayoutを使用して自動的に動作するように私のサンプルを変更する方法はわかりません。 – kresjer

+0

ダイナミックレイアウトマネージャ(デフォルトとは違って)は、コンポーネントが拡大縮小するとき、およびフレームが拡大/縮小するときにコンポーネントの位置を変更するために作成されるため、明示的にコードを記述する必要はありません。 – Yishai

3

revalidateinvalidateの代わりに。 invalidateは、レイアウトを必要とするものとしてコンテナをマークするだけです。 revalidateを実行してからvalidateをスケジュールします。

ご意見:JFrameおよび他のコンポーネントからの延長は避けてください。インタフェースの多重継承を避け、(変更可能な)統計を避けてください。

+1

最後の段落のTomに詳しく説明できますか?特に、コンポーネントの拡張を避けるべき理由は何ですか? – Pool

+0

ソースコードでinvalidate()をrevalidate()に変更しても、まだ動作していません - あるいは何か他に提案していますか? 私のコードは醜いと知っていますが(私はあなたが与えたすべての提案を知っていないかもしれませんが、私は見ています)、私の例を1つのクラスに合わせたいと思っていました。 – kresjer

+0

@Poolインターフェイスの多重継承についてはわかりません(最初はインターフェイスの半分のようです)。しかし、コンポーネントを拡張するとAPIが汚染される傾向があり、誰もが使用することが難しくなります。代わりに、コンポーネントをクラスのメンバーにして、必要に応じてアクセスするための 'getUI'のようなメソッドを提供したいとします。 –

-3

updateUI();は決して失敗しないでください!

+0

LAUIの変更にはupdateUI()が使用されます。これはLAFの変更ではないため、使用しないでください。 – camickr

0

JTextAreaのみの無効化または検証は機能しません。自動的にサイズが更新されないため、上部フレームのサイズを変更する必要があります。たとえば、あなたはこのようにそれを行うことができます(静的変数を削除するには、少しのコードを変更):

package layouttest; 

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JTextArea;  

public class LayoutTestStart extends JFrame implements ActionListener{ 

private JTextArea f = new JTextArea("A medium sized text"); 

public LayoutTestStart(){ 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    JPanel all = new JPanel(); 
    JButton button = new JButton("Expand"); 
    button.addActionListener(this); 

    all.add(button); 
    all.add(f); 
    getContentPane().add(all); 
} 

@Override 
public void actionPerformed(ActionEvent e){ 
    javax.swing.SwingUtilities.invokeLater(new Runnable(){   
     @Override 
     public void run(){ 
      f.setText(f.getText() + "\n" + f.getText()); 
      setSize(getPreferredSize());     
     } 
    }); 

} 

public static void main(String[] args){ 
    // Schedule a job for the event-dispatching thread: 
    // creating and showing this application's GUI. 
    javax.swing.SwingUtilities.invokeLater(new Runnable(){ 
     public void run(){ 
      LayoutTestStart lst = new LayoutTestStart(); 
      lst.setVisible(true); 
      lst.pack(); 
     } 
    }); 
} 
} 
関連する問題