2012-04-20 11 views
2

実験の結果、SwingのGroupLayoutは、GUI上で再利用が意図されているコンポーネントを失う傾向があることがわかりました。SwingのGroupLayoutおよびsetContentPane - コンポーネントを失っていますか?

しかし、この一回限りのルールをクリアするようなドキュメントでは何も見ていません。これは私が間違いを犯したのか、私が貧しい読者であるのか不思議に思います。

たとえば、JButton( "Foo")のGroupLayoutを使用してJPanelを作成します。次に、同じJButtonのGroupLayoutを "Bar"に変更して別のJPanelを作成します。

JFrame.setContentPaneを使用して2番目のJPanelから最初のJPanelに切り替えると、最初のJPanelでJButtonが失われます。

コンポーネントが失われている理由を説明できる人は誰ですか?また、コンポーネントを失う傾向を克服する方法を誰にも提供できますか?ここで

は、問題を実証する完全SSCCEです:

import javax.swing.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

public class GroupLayoutTest { 

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      deployGroupLayoutTest(); 
     } 
    }); 
} 

static JPanel firstPanel; 
static JButton jbtnActionLog; 
static JFrame systemFrame; 

public static void deployGroupLayoutTest() { 
    systemFrame = new JFrame("Group Layout Test"); 
    systemFrame.setSize(300, 300); 

    firstPanel = new JPanel(); 

    JMenuBar jmbSystem = new JMenuBar(); 

    JMenu jmuAction = new JMenu("Action"); 

    JMenuItem jmiActionLog = new JMenuItem("Login"); 
    jmuAction.add(jmiActionLog); 

    jmbSystem.add(jmuAction); 

    jbtnActionLog = new JButton("Login"); 
    jbtnActionLog.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      setContentPaneToSecondPanel(); 
     } 
    }); 

    systemFrame.setJMenuBar(jmbSystem); 

    GroupLayout gl = new GroupLayout(firstPanel); 
    firstPanel.setLayout(gl); 
    gl.setAutoCreateContainerGaps(true); 
    gl.setAutoCreateGaps(true); 

    GroupLayout.ParallelGroup hGroup = gl.createParallelGroup(GroupLayout.Alignment.CENTER); 
    hGroup 
      .addComponent(jbtnActionLog); 

    gl.setHorizontalGroup(hGroup); 

    GroupLayout.SequentialGroup vGroup = gl.createSequentialGroup(); 
    vGroup 
      .addComponent(jbtnActionLog); 
    gl.setVerticalGroup(vGroup); 

    systemFrame.getContentPane().add(firstPanel); 
    systemFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    systemFrame.setLocationByPlatform(true); 
    systemFrame.setVisible(true); 

} 

public static void setContentPaneToSecondPanel() { 
    jbtnActionLog.setText("Logout"); 
    ActionListener[] listenerList = jbtnActionLog.getActionListeners(); 
    jbtnActionLog.removeActionListener(listenerList[0]); 
    jbtnActionLog.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      systemFrame.setContentPane(firstPanel); 
      systemFrame.revalidate(); 
     } 
    }); 

    JPanel secondPanel = new JPanel(); 

    GroupLayout gl = new GroupLayout(secondPanel); 
    secondPanel.setLayout(gl); 
    gl.setAutoCreateContainerGaps(true); 
    gl.setAutoCreateGaps(true); 

    GroupLayout.ParallelGroup hGroup = gl.createParallelGroup(GroupLayout.Alignment.CENTER); 
    hGroup 
      .addComponent(jbtnActionLog); 

    gl.setHorizontalGroup(hGroup); 

    GroupLayout.SequentialGroup vGroup = gl.createSequentialGroup(); 
    vGroup 
      .addComponent(jbtnActionLog); 
    gl.setVerticalGroup(vGroup); 

    systemFrame.setContentPane(secondPanel); 
    systemFrame.revalidate(); 
} 

}

答えて

2

私はあなたのコードのすべてを通過しませんでしたが、複数の親に、単一のSwingコンポーネントを追加するだけでは不可能です。各コンポーネントは、Swing階層の1つの場所にしか存在できません。だから、コード

JPanel firstPanel = ...; 
JPanel secondPanel = ...; 
JButton button = ...; 
firstPanel.add(button); 
secondPanel.add(button); 

は唯一の両方でのパネルの1つに含まれ、ないbuttonになります。これはGroupLayoutとは関係ありません。

関連SO questionは、これを説明するSwing tutorialへのリンクが含まれています

各GUIコンポーネントは一度だけ含有させることができます。コンポーネントが既にコンテナ内にあり、それを別のコンテナに追加しようとすると、コンポーネントは最初のコンテナから削除され、次に追加されます。

+0

Aha!この問題を説明していただきありがとうございます。私は、問題への答えは新しいコンポーネントを生成することですが、同じActionまたはActionListener ... +1で明確かつ有益な答えを得ることです。 – Arvanem

関連する問題