使用cardlayout在面板之间切换时,JTextField和按钮不会更新

时间:2016-02-06 22:19:28

标签: java swing jbutton jtextfield cardlayout

我一直在努力在几天内在cardlayout中更新Jtextfield和Jbutton数据。我已经创建了一个小的演示来解释我的问题..当我点击“开始”按钮时它应该显示另一个面板并且这是有效但当我返回主页面时我希望我的Jtextfield和jbutton从“world”更新为“你好”,但这不起作用。任何帮助和建议将不胜感激。(抱歉代码缩进,我不知道为什么复制粘贴不能正常工作)。

  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);
     }
  }

2 个答案:

答案 0 :(得分:3)

当此行在您的侦听器中执行时:

CardlayoutDemo.data = "hello";

您正在创建一个新的java.lang.String对象并设置字段数据以引用您刚刚创建的新String。这对JTextField的内部状态或先前由变量引用的String对象没有影响。

要更改JTextField的文本,您应该调用JTextField的setText(String)方法。

答案 1 :(得分:2)

不,不要覆盖show方法。而是给你的类方法允许其他类改变它们的状态。例如,您可以将此方法添加到IntroPanel类:

class IntroPanel {
    // .....

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

然后在想要更改其lblData字段的状态时调用它:

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!"); // !!
    }
});

请注意,这是一个快速而肮脏的解决方案。如果您想要一个更强大的解决方案,可以在更大的程序中更好地扩展,那么可以沿着M-V-C设计模式重新构建程序,并让您的视图更改显示的文本以响应模型中String状态的变化。这将需要更多的工作,并在一个小玩具"程序不值得付出努力,但是在一个大型的复杂程序中非常值得付出努力,因为它有助于减少耦合,从而降低复杂性和错误风险。