Modifying independent JPanels from the JFrame

后端 未结 1 571
无人及你
无人及你 2021-01-24 00:54

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

相关标签:
1条回答
  • 2021-01-24 01:44
    1. Use MVC, Model-View-Control, separation of concerns.
    2. Have the Control, which holds your listeners, change the state of the model.
    3. The Views -- your GUI's, have listeners added to them by the control, so that user input is transmitted to the control and thereby to the model.
    4. The View can also either directly add listeners to the model so that they can change their display if the model changes, or often this is done indirectly through the control.
    5. Don't add MouseListeners to JButtons. Use ActionListeners as that's what they're for. For example, if you disable a JButton, any ActionListeners attached to it won't work -- which is correct behavior. The same is not true for MouseListeners.

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


    Edit
    For example:

    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).

    0 讨论(0)
提交回复
热议问题