简体   繁体   English

显示下一面板时更新CardLayout中的JLables

[英]Updating JLables In CardLayout When Showing Next Panel

I have a CardLayout composed of numerous different JPanels which I show at will. 我有一个CardLayout,它由许多不同的JPanels组成,我可以随意显示。 This GUI is linked to a backend, and the purpose of the GUI is to allow the user to manipulate the data which is stored in the backend. 该GUI链接到后端,并且GUI的目的是允许用户操纵存储在后端中的数据。

The problem is, when the user changes some data in the backend, my JLabels are not reflecting the change in that data. 问题是,当用户在后端更改某些数据时,我的JLabel无法反映该数据中的更改。 I understand that this is because the JLabels are initialized once, and when I update the variables that they are initialized to, I must call setText again in order for them to experience the change. 我知道这是因为JLabel初始化了一次,并且在更新它们初始化为的变量时,必须再次调用setText才能使它们经历更改。

Example: Here is how my JLabel is initialized 示例:这是我的JLabel初始化的方式

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

The problem is, when I change the value of GUI.currentBankAccount.getAccountName() , the text on my JLabel does not update. 问题是,当我更改GUI.currentBankAccount.getAccountName()的值时,JLabel上的文本不会更新。 I have JLabels like this all over the place, and it would be a pain to have to go through and manually call setText on all of them each time a user makes any kind of change. 我到处都有这样的JLabel,每当用户进行任何类型的更改时,都要经历遍历并手动调用setText会很痛苦。 Is there any way that I can have the JLabel automatically update itself when the value of that variable changes? 有什么方法可以让JLabel在该变量的值更改时自动更新自身?

Perhaps I could implement some sort of Observer pattern? 也许我可以实现某种观察者模式? How would I do this with JLabels? 我将如何用JLabels做到这一点?
Or maybe I could use a focusGained Event so that every time I switch to a panel, the focusGained event fires so that I can update things. 或者,也许我可以使用focusGained事件,以便每次切换到面板时都会触发focusGained事件,以便我进行更新。 I am not sure how to do this though, and I am not sure how focus works with CardLayout. 我不确定如何执行此操作,也不确定CardLayout如何工作。 Maybe just a method that gets called every time I show a panel with layout.show(..) . 也许只是我每次显示带有layout.show(..)的面板时都会调用的方法。 How would I implement this? 我将如何实施呢?
Is there a better way? 有没有更好的办法?

Update: Sample Code 更新:示例代码

GUI.java is my main GUI class and will consist of a JPanel to which all of my pages will be added and shown at will. GUI.java是我的主要GUI类,它将包含一个JPanel,我的所有页面都将添加到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 will be a JPanel with the JLabel that I want to be updated on it 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 will be a JPanel with a button on it which when pressed, will update the variable that the text of the JLabel in DisplayPanel is set to. 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;                   
}

You need to use a notification system by having the view (the GUI) be notified by the model (the "backend") when data has been changed. 您需要通过在数据已更改时由模型(“后端”)通知视图(GUI)来使用通知系统。 Then the view can request the updated information and use it to update the JLabel display. 然后,视图可以请求更新的信息,并使用它来更新JLabel显示。 The details of this will depend on the specifics of your code, but I often give my model (or a wrapper around the model) a SwingPropertyChangeSupport field as well as addPropertyChangeListener(...) and the similar remove listener methods, and then in the model's methods where a property is changed (a bound property), fire the SwingPropertyChangeSupport's notification method. 具体细节取决于代码的细节,但是我经常给我的模型(或模型的包装)一个SwingPropertyChangeSupport字段以及addPropertyChangeListener(...)和类似的remove监听器方法,然后在更改属性( 绑定属性)的模型方法,则触发SwingPropertyChangeSupport的通知方法。 For more details on an implementation, you should consider showing some details of your code, preferably a minimal example program . 有关实现的更多详细信息,您应该考虑显示代码的一些详细信息,最好是一个最小的示例程序

For example 例如


Edit 编辑

Note that if all you want is notification of when show is called, you can always extend CardLayout and override its show(...) method. 请注意,如果只需要通知何时调用show,则可以始终扩展CardLayout并覆盖其show(...)方法。 But if you do this, don't forget to call the super.show(...) method as well. 但是,如果执行此操作,也不要忘记调用super.show(...)方法。


Edit 编辑
Note changes made to code indicated by // !! 注意对// !!指示的代码所做的更改// !!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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