从 JFrame 修改独立的 JPanel

2022-01-24 00:00:00 java swing jpanel jframe

我有一个带有两个独立 JPanel 的 JFrame.其中一个 JPanel 充满了 JButton,而另一个则有几个文本字段.我通过 JFrame 向按钮添加了鼠标侦听器,并且我想这样做,以便当从第一个 JPanel 触发事件时,第二个 JPanel 中的文本字段会发生更改.这两个面板有自己的类.我该怎么做呢?

I've got a JFrame with two separate JPanels. One of the JPanels is filled with JButtons while the other has a couple of text fields. I added mouse listeners to the buttons via the JFrame and I want to make it so that when an event is fired from the first JPanel, the text fields in the second JPanel are changed. The two panels have their own classes. How would I go about doing this?

推荐答案

  1. 使用 MVC、模型-视图-控制、关注点分离.
  2. 让包含您的侦听器的控件更改模型的状态.
  3. 视图 - 您的 GUI,控件添加了侦听器,以便将用户输入传输到控件,从而传输到模型.
  4. View 也可以直接向模型添加侦听器,以便在模型更改时它们可以更改其显示,或者通常通过控件间接完成.
  5. 不要将 MouseListeners 添加到 JButtons.使用 ActionListeners,因为这就是它们的用途.例如,如果您禁用一个 JButton,任何附加到它的 ActionListener 都将不起作用——这是正确的行为.MouseListener 的情况并非如此.

如需更具体的帮助,请考虑创建和发布最小示例程序.

For more specific help, consider creating and posting a minimal example program.

编辑
例如:

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

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.SwingPropertyChangeSupport;

public class MvcMain {
   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            MvcView view = new MvcView();
            MvcModel model = new MvcModel();
            MvcControl control = new MvcControl(view, model);
            view.createAndDisplay();
         }
      });
   }
}

class MvcView {
   private MvcModel model;
   private ButtonPanel buttonPanel = new ButtonPanel();
   private TextFieldPanel textFieldPanel = new TextFieldPanel();
   private JPanel mainPanel = new JPanel();

   public MvcModel getModel() {
      return model;
   }

   public ButtonPanel getButtonPanel() {
      return buttonPanel;
   }

   public TextFieldPanel getTextFieldPanel() {
      return textFieldPanel;
   }

   public MvcView() {
      mainPanel.setLayout(new GridLayout(0, 1));
      mainPanel.add(textFieldPanel);
      mainPanel.add(buttonPanel);
   }

   public void setModel(MvcModel model) {
      this.model = model;
      model.addPropertyChangeListener(new ModelListener());
   }

   public void createAndDisplay() {
      JFrame frame = new JFrame("MVC Test");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(mainPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   private class ModelListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         if (ButtonTitle.class.getCanonicalName().equals(evt.getPropertyName())) {
            ButtonTitle newValue = model.getButtonTitle();
            textFieldPanel.textFieldSetText(newValue.getTitle());
         }
      }
   }
}

enum ButtonTitle {
   START("Start"), STOP("Stop"), PAUSE("Pause");
   private String title;

   private ButtonTitle(String title) {
      this.title = title;
   }

   public String getTitle() {
      return title;
   }
}

@SuppressWarnings("serial")
class ButtonPanel extends JPanel {
   public ButtonPanel() {
      setBorder(BorderFactory.createTitledBorder("Button Panel"));
      setLayout(new GridLayout(1, 0, 5, 0));
      for (ButtonTitle btnTitle : ButtonTitle.values()) {
         add(new JButton(new ButtonAction(btnTitle)));
      }
   }

   private class ButtonAction extends AbstractAction {
      private ButtonTitle btnTitle;

      public ButtonAction(ButtonTitle btnTitle) {
         super(btnTitle.getTitle());
         this.btnTitle = btnTitle;
      }

      public void actionPerformed(java.awt.event.ActionEvent e) {
         Object oldValue = null;
         ButtonTitle newValue = btnTitle;
         ButtonPanel.this.firePropertyChange(
               ButtonTitle.class.getCanonicalName(), oldValue, newValue);
      };
   }
}

@SuppressWarnings("serial")
class TextFieldPanel extends JPanel {
   private JTextField textField = new JTextField(15);

   public TextFieldPanel() {
      setBorder(BorderFactory.createTitledBorder("TextField Panel"));
      add(textField);
   }

   public void textFieldSetText(String text) {
      textField.setText(text);
   }
}

class MvcControl {
   private MvcView view;
   private MvcModel model;

   public MvcControl(MvcView view, MvcModel model) {
      this.view = view;
      this.model = model;
      view.setModel(model);
      view.getButtonPanel().addPropertyChangeListener(new ButtonPanelListener());
   }

   private class ButtonPanelListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         if (ButtonTitle.class.getCanonicalName().equals(evt.getPropertyName())) {
            ButtonTitle newValue = (ButtonTitle) evt.getNewValue();
            model.setButtonTitle(newValue);
         }
      }
   }
}

class MvcModel {
   private ButtonTitle buttonTitle;
   private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
         this);

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(listener);
   }

   public ButtonTitle getButtonTitle() {
      return buttonTitle;
   }

   public void setButtonTitle(ButtonTitle buttonTitle) {
      ButtonTitle oldValue = this.buttonTitle;
      ButtonTitle newValue = buttonTitle;
      this.buttonTitle = buttonTitle;
      pcSupport.firePropertyChange(ButtonTitle.class.getCanonicalName(),
            oldValue, newValue);
   }
}

该示例缺少使用接口,这将允许进一​​步分离关注点,从而导致更松散的耦合(一件好事).

The example is lacking in use of interfaces which would allow for a further separation of concerns resulting in looser coupling (a good thing).

相关文章