简体   繁体   中英

JTextField and button is not updated while switching between panel using cardlayout

I have been struggling with updating Jtextfield and Jbutton data in cardlayout from couple of days. I have created small demo to explain my problem.. When I click on "start" button it should show another panel and thats is working but when I return back to main page I want my Jtextfield and jbutton to be updated from "world" to "hello" but that is not working. Any help and suggestions would be appreciated.(Sorry about the indentation of code, I do not know why copy-paste did not work properly).

  public class CardlayoutDemo {

     public static String data = "world";
     private static final String INTRO = "intro";
     private static final String GAME = "game";
     private CardLayout cardlayout = new CardLayout();
     private JPanel mainPanel = new JPanel(cardlayout);
     private IntroPanel introPanel = new IntroPanel();
     private GamePanel gamePanel = new GamePanel();
  public CardlayoutDemo() {
        mainPanel.add(introPanel.getMainComponent(), INTRO);
  mainPanel.add(gamePanel.getMainComponent(), GAME);

  introPanel.addBazBtnActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
         CardlayoutDemo.data = "hello";
         mainPanel.repaint();
         mainPanel.revalidate();
         CardLayout cl = (CardLayout)mainPanel.getLayout();
        cl.show(mainPanel, GAME);
     }
  });

  gamePanel.addBackBtnActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
         CardLayout cl = (CardLayout)mainPanel.getLayout();
        cl.show(mainPanel, INTRO);
     }
  });
     }

     private JComponent getMainComponent() {
  return mainPanel;
     }

     private static void createAndShowUI() {
  JFrame frame = new JFrame("Demo");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.getContentPane().add(new CardlayoutDemo().getMainComponent());
  frame.pack();
  frame.setLocationRelativeTo(null);
  frame.setVisible(true);
     }

     public static void main(String[] args) {
  java.awt.EventQueue.invokeLater(new Runnable() {
     public void run() {
        createAndShowUI();
     }
  });
     }
  }

  class IntroPanel {
     private JPanel mainPanel = new JPanel();
     public JButton start;
     private JButton exit;
     private JTextField lblData;

     public IntroPanel() {
  mainPanel.setLayout(new BorderLayout());
  JPanel content = new JPanel();
  start = new JButton("Start");
  exit = new JButton(CardlayoutDemo.data);
  lblData = new JTextField(CardlayoutDemo.data);
  content.add(lblData);
  content.add(start);
  content.add(exit);
  mainPanel.add(content, BorderLayout.CENTER);

  exit.addActionListener(new ActionListener() {
     @Override
     public void actionPerformed(ActionEvent e) {
        Window win = SwingUtilities.getWindowAncestor(mainPanel);
        win.dispose();
     }
  });
     }
     public void addBazBtnActionListener(ActionListener listener) {
        start.addActionListener(listener);
     }
     public JComponent getMainComponent() {
        return mainPanel;
     }
  }

  class GamePanel {
     private static final Dimension MAIN_SIZE = new Dimension(400, 200);
     private JPanel mainPanel = new JPanel();
     private JButton back;

     public GamePanel() {
        back = new JButton("return to main menu");
        mainPanel.add(back);
  mainPanel.setPreferredSize(MAIN_SIZE);
     }

     public JComponent getMainComponent() {
        return mainPanel;
     }

     public void addBackBtnActionListener(ActionListener listener) {
        back.addActionListener(listener);
     }
  }

when this line gets executed inside your listener:

CardlayoutDemo.data = "hello";

You´re creating a new java.lang.String object and setting the field data to reference the new String you have just created. This has no effect over the internal state of the JTextField or the String object which was previously referenced by the variable.

To change the text of the JTextField you should call the setText(String) method of JTextField .

No, don't override the show method. Instead give your classes methods that allow other classes the ability to change their state. For instance, you could add this method to the IntroPanel class:

class IntroPanel {
    // .....

    // !! added!
    public void lblDataSetText(String text) {
        lblData.setText(text);
    }
}

and then call it when you want to change the state of its lblData field:

introPanel.addBazBtnActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // !! CardlayoutDemo.data = "hello";
        mainPanel.repaint();
        mainPanel.revalidate();
        CardLayout cl = (CardLayout) mainPanel.getLayout();
        cl.show(mainPanel, GAME);
        introPanel.lblDataSetText("Hello!"); // !!
    }
});

Note that this is a quick and dirty solution. If you want a more robust solution that scales better in larger programs, then re-structure your program along an MVC design pattern, and have your view change the displayed text in response to a change in the state of a String in the model. This would require more work, and in a small "toy" program wouldn't be worth the effort, but in a large complex program is well worth the effort since it would help reduce coupling and thereby reduce complexity and risk of bugs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM