2014-11-11 2 views
0

나는 마음대로 보여줄 수있는 수많은 다른 JPanel로 구성된 CardLayout을 가지고 있습니다. 이 GUI는 백엔드에 링크되어 있으며 GUI의 목적은 사용자가 백엔드에 저장된 데이터를 조작 할 수있게하는 것입니다.CardLayout에서 JLables를 업데이트 할 때 다음 패널을 표시 할 때

문제는 사용자가 백엔드에서 일부 데이터를 변경하면 JLabel이 해당 데이터의 변경 내용을 반영하지 않는다는 것입니다. 나는 이것이 JLabel이 한번 초기화 되었기 때문에 이것이 내가 초기화 한 변수를 업데이트 할 때 변경을 경험하기 위해서 다시 setText를 호출해야한다는 것을 이해한다.

예 : 여기 내 JLabel의이

CurrentBAName = new javax.swing.JLabel(); 
CurrentBAName.setText(GUI.currentBankAccount.getAccountName()); 

문제는 초기화됩니다 내가 GUI.currentBankAccount.getAccountName()의 값을 변경할 때, 내 JLabel의의 텍스트가 업데이트되지 않는 방법이다. JLabel이 여기 저기에 있는데, 사용자가 어떤 종류의 변경을 할 때마다 setText를 수동으로 호출해야합니다. 해당 변수의 값이 변경되면 JLabel을 자동으로 업데이트 할 수있는 방법이 있습니까?

아마도 Observer 패턴을 구현할 수 있습니까? JLabels로 어떻게하면 좋을까요?
또는 focusGained 이벤트를 사용하여 패널로 전환 할 때마다 focusGained 이벤트가 발생하여 업데이트 할 수 있습니다. 어떻게해야할지 모르겠다. CardLayout과 포커스가 어떻게 작용하는지 잘 모르겠다. layout.show(..)으로 패널을 표시 할 때마다 호출되는 메서드 일 수 있습니다. 어떻게 구현할 수 있습니까?
더 좋은 방법이 있습니까?

업데이트 : 샘플 코드

GUI.java 내 주요 GUI 클래스이며, JPanel의 어떤 내 모든 페이지에 추가하고 의지에 표시됩니다에 구성됩니다.

import javax.swing.*; 

public class GUI extends javax.swing.JFrame 
{ 
    public static String item; 
    private javax.swing.JPanel MainPanel; 

    public GUI() 
    { 
     // creates a JPanel called MainPanel which will hold the cards 
     // in my CardLayout 
     initComponents(); 
    } 

    private void initComponents() 
    { 

     MainPanel = new javax.swing.JPanel(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

     MainPanel.setBackground(new java.awt.Color(198, 118, 38)); 
     MainPanel.setMaximumSize(new java.awt.Dimension(1000, 1000)); 
     MainPanel.setName(""); // NOI18N 
     MainPanel.setPreferredSize(new java.awt.Dimension(1024, 768)); 
     MainPanel.setLayout(new java.awt.CardLayout()); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
       layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
       .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 
         .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 
         .addComponent(MainPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
         .addContainerGap()) 
     ); 
     layout.setVerticalGroup(
       layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
       .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 
         .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 
         .addComponent(MainPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) 
         .addContainerGap()) 
     ); 

     pack(); 
     setLocationRelativeTo(null); 

    } 

    // Grab the panel that was created in initComponents() so that I can add 
    // other panels to it 
    public JPanel getMainPanel() 
    { 
     return MainPanel; 
    } 

    public static void main(String args[]) 
    { 
     java.awt.EventQueue.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       GUI mainGUI = new GUI(); 

       // The JLabel in DisplayPanel.java will initially say root 
       item = "root"; 

       JPanel cardHolder = mainGUI.getMainPanel(); 
       //This panel contains a button which will update the name of 
       //the currentUserAccount 
       MainMenuPanel mainMenu = new MainMenuPanel(cardHolder); 
       cardHolder.add(mainMenu, "MainMenu"); 

       //This panel holds a JLabel that I want to have updated automatically 
       //when the user presses the button on MainMenuPanel 
       DisplayPanel display = new DisplayPanel(cardHolder); 
       cardHolder.add(display, "Display"); 

       mainGUI.pack(); 
       mainGUI.setVisible(true); 
      } 
     }); 
    } 
} 

DisplayPanel.java 내가 그것을 업데이트 할 JLabel의와 JPanel의이

import java.awt.*; 
import javax.swing.*; 

public class DisplayPanel extends javax.swing.JPanel 
{ 
    private JPanel MainPanel; 

    public DisplayPanel(JPanel MainPanel) 
    { 

     this.MainPanel = MainPanel; 
     initComponents(); // Creates my panel with the JLabels/buttons etc 
    } 

    @SuppressWarnings("unchecked")     
    private void initComponents() 
    { 

     jLabel1 = new javax.swing.JLabel(); 
     GoToMainMenuButton = new javax.swing.JButton(); 

     jLabel1.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N 
     jLabel1.setText(GUI.item); // sets the JLabel to the GUI.item variable 

     GoToMainMenuButton.setText("Go to MainMenuPanel"); 
     GoToMainMenuButton.addMouseListener(new java.awt.event.MouseAdapter() 
     { 
      public void mouseClicked(java.awt.event.MouseEvent evt) 
      { 
       GoToMainMenuButtonMouseClicked(evt); 
      } 
     }); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); 
     this.setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 
       .addContainerGap(269, Short.MAX_VALUE) 
       .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
        .addComponent(GoToMainMenuButton) 
        .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)) 
       .addGap(266, 266, 266)) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addGap(168, 168, 168) 
       .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE) 
       .addGap(83, 83, 83) 
       .addComponent(GoToMainMenuButton) 
       .addContainerGap(116, Short.MAX_VALUE)) 
     ); 
    }      

    private void GoToMainMenuButtonMouseClicked(java.awt.event.MouseEvent evt)             
    { 
     // go back to the MainPanel           
     CardLayout layout = (CardLayout) (MainPanel.getLayout()); 
     layout.show(MainPanel, "MainMenu"); 
    }            

    private javax.swing.JButton GoToMainMenuButton; 
    private javax.swing.JLabel jLabel1; 

} 

MainMenuPanel.java 그것에 버튼으로 JPanel을 될 것입니다 될 것이다 때 눌렀 으면 DisplayPanel의 JLabel 텍스트가 설정된 변수가 업데이트됩니다.

import java.awt.*; 
import javax.swing.*; 

public class MainMenuPanel extends javax.swing.JPanel 
{ 

    private JPanel MainPanel; 

    public MainMenuPanel(JPanel MainPanel) 
    { 

     this.MainPanel = MainPanel; 
     initComponents(); // Creates my panel with the JLabels/buttons etc 
    } 

    @SuppressWarnings("unchecked")       
    private void initComponents() 
    { 

     GoToDisplayPanelButton = new javax.swing.JButton(); 

     GoToDisplayPanelButton.setText("Press Me"); 
     GoToDisplayPanelButton.addMouseListener(new java.awt.event.MouseAdapter() 
     { 
      public void mouseClicked(java.awt.event.MouseEvent evt) 
      { 
       GoToDisplayPanelButtonMouseClicked(evt); 
      } 
     }); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); 
     this.setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addGap(252, 252, 252) 
       .addComponent(GoToDisplayPanelButton) 
       .addContainerGap(260, Short.MAX_VALUE)) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() 
       .addContainerGap(198, Short.MAX_VALUE) 
       .addComponent(GoToDisplayPanelButton) 
       .addGap(175, 175, 175)) 
     ); 
    }      

    private void GoToDisplayPanelButtonMouseClicked(java.awt.event.MouseEvent evt)              
    {               
     // Changes the value of item. I want this change to be reflected on my 
     // JLabel in DisplayPanel.java, but it is not because I do not explicitly 
     // call setText on the JLabel here. I am wondering if there is a way to 
     // have my JLabel automatically update when the variable in its setText 
     // is changed, without having to directly call setText. Or some other 
     // way to update it without calling setText every time I change something. 
     GUI.item = "new value"; 

     // Switches to my DisplayPanel which should show the updated name in its JLabel 
     CardLayout layout = (CardLayout)(MainPanel.getLayout()); 
     layout.show(MainPanel, "Display"); 
    }             

    private javax.swing.JButton GoToDisplayPanelButton;     
} 
+1

로 표시 코드 http://stackoverflow.com/help/mcve). –

+0

코드를 작성하고 게시 해 주셔서 감사하지만 컴파일되지 않으며 실행되지 않습니다. 이 문제를 해결하십시오. –

+0

** ** 적절한 MCVE입니다. 감사와 1+. –

답변

3

당신은 데이터가 변경되었을 때 모델 (이하 "백엔드")로 통보 뷰 (GUI를)함으로써 통지 시스템을 사용해야합니다. 그런 다음 뷰는 업데이트 된 정보를 요청하고이를 사용하여 JLabel 디스플레이를 업데이트 할 수 있습니다. 이것에 대한 세부 사항은 코드의 특성에 따라 다르지만, 종종 모델 (또는 모델 주위의 래퍼)에 SwingPropertyChangeSupport 필드와 addPropertyChangeListener(...) 및 이와 유사한 리스너 메소드를 제공 한 다음 모델의 메소드에서 속성 (바운드 속성) 변경된 경우 SwingPropertyChangeSupport의 알림 메서드를 시작합니다. 구현에 대한 자세한 내용은 코드의 일부 세부 정보 (예 : minimal example program)를 표시하는 것이 좋습니다.


당신이 원하는 모든 쇼가 호출 될 때 통지하는 경우, 당신은 항상 CardLayout을 확장하고 show(...) 메소드를 오버라이드 (override) 할 수있는 편집

For example

. 그러나이 작업을 수행하는 경우 super.show(...) 메서드를 호출하는 것을 잊지 마십시오. 만든


편집
주 변화, 당신은, 바람직하게는 [최소한의 예제 프로그램] 코드의 일부 세부 정보를 표시하는 것이 좋습니다 구현에 대한 세부 사항 (내용은 // !!

import java.awt.CardLayout; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class GUI extends javax.swing.JFrame { 
    public static final String ITEM = "item"; 
    public String item; // !! this should not be static! 
    private javax.swing.JPanel MainPanel; 

    public GUI() { 
     // creates a JPanel called MainPanel which will hold the cards 
     // in my CardLayout 
     initComponents(); 
    } 

    // !! 
    public void setItem(String item) { 
     String oldValue = this.item; 
     String newValue = item; 
     this.item = item; 
     firePropertyChange(ITEM, oldValue, newValue); 
    } 

    //!! 
    public String getItem() { 
     return item; 
    } 

    private void initComponents() { 

     MainPanel = new javax.swing.JPanel(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

     MainPanel.setBackground(new java.awt.Color(198, 118, 38)); 
     MainPanel.setMaximumSize(new java.awt.Dimension(1000, 1000)); 
     MainPanel.setName(""); // NOI18N 
     MainPanel.setPreferredSize(new java.awt.Dimension(1024, 768)); 
     MainPanel.setLayout(new java.awt.CardLayout()); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
      getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(layout.createParallelGroup(
      javax.swing.GroupLayout.Alignment.LEADING).addGroup(
      javax.swing.GroupLayout.Alignment.TRAILING, 
      layout.createSequentialGroup() 
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, 
         Short.MAX_VALUE) 
        .addComponent(MainPanel, 
         javax.swing.GroupLayout.DEFAULT_SIZE, 
         javax.swing.GroupLayout.DEFAULT_SIZE, 
         javax.swing.GroupLayout.PREFERRED_SIZE) 
        .addContainerGap())); 
     layout.setVerticalGroup(layout.createParallelGroup(
      javax.swing.GroupLayout.Alignment.LEADING).addGroup(
      javax.swing.GroupLayout.Alignment.TRAILING, 
      layout.createSequentialGroup() 
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, 
         Short.MAX_VALUE) 
        .addComponent(MainPanel, 
         javax.swing.GroupLayout.DEFAULT_SIZE, 
         javax.swing.GroupLayout.DEFAULT_SIZE, 
         javax.swing.GroupLayout.PREFERRED_SIZE) 
        .addContainerGap())); 

     pack(); 
     setLocationRelativeTo(null); 

    } 

    // Grab the panel that was created in initComponents() so that I can add 
    // other panels to it 
    public JPanel getMainPanel() { 
     return MainPanel; 
    } 

    public static void main(String args[]) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      final GUI mainGUI = new GUI(); 

      // The JLabel in DisplayPanel.java will initially say root 
      // !! item = "root"; 
      mainGUI.setItem("root"); // !! 

      JPanel cardHolder = mainGUI.getMainPanel(); 
      // This panel contains a button which will update the name of 
      // the currentUserAccount 
      final MainMenuPanel mainMenu = new MainMenuPanel(cardHolder, 
        mainGUI); // !! 
      cardHolder.add(mainMenu, "MainMenu"); 

      // This panel holds a JLabel that I want to have updated 
      // automatically 
      // when the user presses the button on MainMenuPanel 
      final DisplayPanel display = new DisplayPanel(cardHolder, mainGUI); // !! 
      cardHolder.add(display, "Display"); 

      mainGUI.pack(); 
      mainGUI.setVisible(true); 

      // !! 
      mainGUI.addPropertyChangeListener(ITEM, 
        new PropertyChangeListener() { 

        @Override 
        public void propertyChange(PropertyChangeEvent pcEvt) { 
         String itemText = mainGUI.getItem(); 
         display.setJLabel1Text(itemText); 
        } 
        }); 
     } 
     }); 
    } 
} 

@SuppressWarnings("serial") 
class DisplayPanel extends javax.swing.JPanel { 
    private JPanel mainPanel; 
    private GUI mainGui; // !! 

    public DisplayPanel(JPanel mainPanel, GUI mainGui) { // !! 

     this.mainPanel = mainPanel; 
     this.mainGui = mainGui;// !! 
     initComponents(); // Creates my panel with the JLabels/buttons etc 
    } 

    // !! added 
    public void setJLabel1Text(String text) { 
     jLabel1.setText(text); 
    } 

    private void initComponents() { 

     jLabel1 = new javax.swing.JLabel(); 
     GoToMainMenuButton = new javax.swing.JButton(); 

     jLabel1.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N 
     // !! jLabel1.setText(GUI.item); // sets the JLabel to the GUI.item 
     // variable 
     jLabel1.setText(mainGui.getItem()); // !! 

     GoToMainMenuButton.setText("Go to MainMenuPanel"); 
     GoToMainMenuButton.addMouseListener(new java.awt.event.MouseAdapter() { 
     public void mouseClicked(java.awt.event.MouseEvent evt) { 
      GoToMainMenuButtonMouseClicked(evt); 
     } 
     }); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); 
     this.setLayout(layout); 
     layout.setHorizontalGroup(layout 
      .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(
        javax.swing.GroupLayout.Alignment.TRAILING, 
        layout.createSequentialGroup() 
         .addContainerGap(269, Short.MAX_VALUE) 
         .addGroup(
           layout.createParallelGroup(
            javax.swing.GroupLayout.Alignment.LEADING) 
            .addComponent(GoToMainMenuButton) 
            .addComponent(
              jLabel1, 
              javax.swing.GroupLayout.PREFERRED_SIZE, 
              145, 
              javax.swing.GroupLayout.PREFERRED_SIZE)) 
         .addGap(266, 266, 266))); 
     layout.setVerticalGroup(layout.createParallelGroup(
      javax.swing.GroupLayout.Alignment.LEADING).addGroup(
      layout.createSequentialGroup() 
        .addGap(168, 168, 168) 
        .addComponent(jLabel1, 
         javax.swing.GroupLayout.PREFERRED_SIZE, 63, 
         javax.swing.GroupLayout.PREFERRED_SIZE) 
        .addGap(83, 83, 83).addComponent(GoToMainMenuButton) 
        .addContainerGap(116, Short.MAX_VALUE))); 
    } 

    private void GoToMainMenuButtonMouseClicked(java.awt.event.MouseEvent evt) { 
     // go back to the MainPanel 
     CardLayout layout = (CardLayout) (mainPanel.getLayout()); 
     layout.show(mainPanel, "MainMenu"); 
    } 

    private javax.swing.JButton GoToMainMenuButton; 
    private javax.swing.JLabel jLabel1; 

} 

@SuppressWarnings("serial") 
class MainMenuPanel extends javax.swing.JPanel { 

    private JPanel MainPanel; 
    private GUI mainGui; // !! 

    public MainMenuPanel(JPanel MainPanel, GUI mainGui) { // !! 

     this.MainPanel = MainPanel; 
     this.mainGui = mainGui; // !! 
     initComponents(); // Creates my panel with the JLabels/buttons etc 
    } 

    private void initComponents() { 

     GoToDisplayPanelButton = new javax.swing.JButton(); 

     GoToDisplayPanelButton.setText("Press Me"); 
     GoToDisplayPanelButton 
      .addMouseListener(new java.awt.event.MouseAdapter() { 
       public void mouseClicked(java.awt.event.MouseEvent evt) { 
        GoToDisplayPanelButtonMouseClicked(evt); 
       } 
      }); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); 
     this.setLayout(layout); 
     layout.setHorizontalGroup(layout.createParallelGroup(
      javax.swing.GroupLayout.Alignment.LEADING).addGroup(
      layout.createSequentialGroup().addGap(252, 252, 252) 
        .addComponent(GoToDisplayPanelButton) 
        .addContainerGap(260, Short.MAX_VALUE))); 
     layout.setVerticalGroup(layout.createParallelGroup(
      javax.swing.GroupLayout.Alignment.LEADING).addGroup(
      javax.swing.GroupLayout.Alignment.TRAILING, 
      layout.createSequentialGroup() 
        .addContainerGap(198, Short.MAX_VALUE) 
        .addComponent(GoToDisplayPanelButton).addGap(175, 175, 175))); 
    } 

    private void GoToDisplayPanelButtonMouseClicked(java.awt.event.MouseEvent evt) { 
     // Changes the value of item. I want this change to be reflected on my 
     // JLabel in DisplayPanel.java, but it is not because I do not explicitly 
     // call setText on the JLabel here. I am wondering if there is a way to 
     // have my JLabel automatically update when the variable in its setText 
     // is changed, without having to directly call setText. Or some other 
     // way to update it without calling setText every time I change something. 
     // !! GUI.item = "new value"; 
     mainGui.setItem("new value"); // !! 

     // Switches to my DisplayPanel which should show the updated name in its 
     // JLabel 
     CardLayout layout = (CardLayout) (MainPanel.getLayout()); 
     layout.show(MainPanel, "Display"); 
    } 

    private javax.swing.JButton GoToDisplayPanelButton; 
} 
+0

어떤 종류의 세부 사항이 필요하십니까? 나는 기본적으로 다양한 개인 회원을 가진 객체의 HashTable을 가지고있다. 비공개 멤버 중 하나가 설정자를 통해 변경되면 모든 부분을 업데이트하기 위해 GUI가 필요합니다. GUI는 본질적으로 다른 모든 JPanels를 (페이지에) 추가하는 MainPanel (JPanel)입니다. 다양한 페이지는 업데이트가 필요한 JLabel을 포함합니다. – Ryan

+0

@ Ryan : 우리가 필요로하는 것을 정확히 알려주기 때문에 [mcve] (http://stackoverflow.com/help/mcve) 링크를 읽어보십시오. 이 ** **는 전체 프로그램을 한 페이지 또는 두 개의 길이 이상으로보고 싶지 않기 때문에 사용자가 작업해야합니다. 즉, 새로운 작은 데모를 만들어야 할 가능성이 높습니다. 프로그램이지만 그만한 가치가 있습니다. –

+0

@ Ryan : show가 호출되는 시점을 원하는 경우, 항상 CardLayout을 확장하고'show (...) '메소드를 오버라이드 할 수 있습니다. 하지만 그렇게한다면, super.show (...) 메소드를 호출하는 것을 잊지 마라. –

관련 문제