Drawing with paintComponent after value of Jbutton changed in another class

前端 未结 1 1333
北海茫月
北海茫月 2021-01-26 08:38

I have a class named ControlsPanel. If I press a JButton (Start) in this class, the value of a boolean (isPressed) changes to true. In another class (CashRegistersPanel) I want

相关标签:
1条回答
  • 2021-01-26 09:10

    Your issue can be boiled down to simply this: how can one class be notified of a change of state in another class, when the change occurs. This is a common problem in event-driven GUI programs (and other program types as well) and is the whole reason that the observer or listener type design patterns were developed. So my suggestion is just that, that you somehow use a listener design pattern. This can be achieved in several ways including:

    • Allowing the one class to attach an ActionListener to the first class's JButton
    • Having the observer cla add a listener of some type to the class that changes state, the class with the JButton
    • Or my favorite: get the boolean out of your view classes entirely and into a model class, and have any view that wants to be notified to register a listener to the model and react as needed to changes int he model's state. I've used the latter often, often using PropertyChangeListeners to achieve this.

    So a model class could look something like:

    class Model {
       public static final String START = "start"; // for the property change name
       private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
             this);
       private boolean start = false;
    
       public boolean isStart() {
          return start;
       }
    
       public void setStart(boolean start) {
          // to set up our PropertyChangeEvent
          boolean oldValue = this.start;
          boolean newValue = start;
          this.start = start;
    
          // notify our listeners that the start property has changed
          pcSupport.firePropertyChange(START, oldValue, newValue);
       }
    
       // allow listeners to be added and removed
       public void addPropertyChangeListener(PropertyChangeListener listener) {
          pcSupport.addPropertyChangeListener(listener);
       }
    
       public void removePropertyChangeListener(PropertyChangeListener listener) {
          pcSupport.removePropertyChangeListener(listener);
       }
    }
    

    Edit For example, here is a M-V or Model-View simple example program:

    import java.awt.Color;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.beans.PropertyChangeListener;
    
    import javax.swing.*;
    import javax.swing.event.SwingPropertyChangeSupport;
    
    public class VerySimpleModelEg {
       private static void createAndShowGui() {
          Model model = new Model();
          ButtonView view1 = new ButtonView();
          DrawingView view2 = new DrawingView();
    
          view1.setModel(model);
          view2.setModel(model);
    
          JPanel mainPanel = new JPanel(new GridLayout(1, 0));
          mainPanel.add(view1);
          mainPanel.add(view2);
    
          JFrame frame = new JFrame("Very Simple Model Example");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    class Model {
       public static final String START = "start"; // for the property change name
       private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
             this);
       private boolean start = false;
    
       public boolean isStart() {
          return start;
       }
    
       public void setStart(boolean start) {
          // to set up our PropertyChangeEvent
          boolean oldValue = this.start;
          boolean newValue = start;
          this.start = start;
    
          // notify our listeners that the start property has changed
          pcSupport.firePropertyChange(START, oldValue, newValue);
       }
    
       // allow listeners to be added and removed
       public void addPropertyChangeListener(PropertyChangeListener listener) {
          pcSupport.addPropertyChangeListener(listener);
       }
    
       public void removePropertyChangeListener(PropertyChangeListener listener) {
          pcSupport.removePropertyChangeListener(listener);
       }
    }
    
    @SuppressWarnings("serial")
    class ButtonView extends JPanel {
       public static final String PRESS_TO_START = "Press To Start";
       public static final String PRESS_TO_STOP = "Press To Stop";
       private Model model;
       private Action buttonAction = new ButtonAction();
    
       public ButtonView() {
          add(new JButton(buttonAction));
          setBorder(BorderFactory.createTitledBorder("Button View"));
       }
    
       public void setModel(Model model) {
          this.model = model;
          model.addPropertyChangeListener(new BtnViewModelListener());
       }
    
       private class ButtonAction extends AbstractAction {
          public ButtonAction() {
             super(PRESS_TO_START);
          }
    
          @Override
          public void actionPerformed(ActionEvent e) {
    
             // if the button is pressed, toggle the state 
             // of the model's start property
             model.setStart(!model.isStart()); 
          }
       }
    
       private class BtnViewModelListener implements PropertyChangeListener {
          public void propertyChange(java.beans.PropertyChangeEvent evt) {
    
             // if the model's start property changes
             if (Model.START.equals(evt.getPropertyName())) {
                // change the Action's name property
                // which will change the JButton's text too!
                String text = model.isStart() ? PRESS_TO_STOP : PRESS_TO_START;
                buttonAction.putValue(Action.NAME, text);
             }
          };
       }
    
    
    }
    
    @SuppressWarnings("serial")
    class DrawingView extends JPanel {
       private static final Color START_COLOR = Color.red;
       private static final Color STOP_COLOR  = Color.blue;
       private Model model;
    
       public DrawingView() {
          setBorder(BorderFactory.createTitledBorder("Drawing View"));
          setBackground(STOP_COLOR);
       }
    
       public void setModel(Model model) {
          this.model = model;
          model.addPropertyChangeListener(new DrawingViewModelListener());
       }
    
    
       private class DrawingViewModelListener implements PropertyChangeListener {
          public void propertyChange(java.beans.PropertyChangeEvent evt) {
    
             // if the model's start property changes
             if (Model.START.equals(evt.getPropertyName())) {
                // change the color of the JPanel
                Color bg = model.isStart() ? START_COLOR : STOP_COLOR;
                setBackground(bg);
             }
          };
       }
    
    }
    

    And yes, this may be a bit of over-kill for your very simple situation, but it scales up nicely since you can with this separate the model and the GUI concerns.

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