【问题标题】:Drawing with paintComponent after value of Jbutton changed in another class在另一个类中更改 Jbutton 的值后使用 paintComponent 进行绘图
【发布时间】:2014-08-21 00:12:46
【问题描述】:

我有一个名为 ControlsPanel 的类。如果我在此类中按下 JButton (Start),则布尔值 (isPressed) 的值将变为 true。在另一个类(CashRegistersPanel)中,我想绘制一个图像,但只有前一个类中的布尔值是真的。 当然这个布尔值一开始是假的,所以它不会画任何东西。

这是我的两个课程:

    public ControlsPanel(final ParametersPanel panel) {         
        start       = new JButton("Start");
        stop        = new JButton("Stop");          
        start.setFont(new Font("Arial", Font.BOLD, 14));
        stop.setFont(new Font("Arial", Font.BOLD, 14));         
        this.setLayout(null);
        this.setBackground(new Color(199,202,255));         
        this.add(start);
        this.add(stop);         
        start.setBounds(10, 10, 280, 30);
        stop.setBounds(10, 50, 280, 30);            
        stop.setEnabled(false);    
        start.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {

                if (start.getText().equals("Start")) {
                    start.setText("Pause");
                    stop.setEnabled(true);
                    startIsPressed = true;
                }                   
            }
        });    

    public boolean StartisPressed() {
        return startIsPressed;
    }

}

和

public class CashRegistersPanel extends JPanel{

    private Image img;
    private int amount;
    private ParametersPanel parametersPanel;
    private ControlsPanel controlsPanel;
    private boolean startIsPressed;

    public CashRegistersPanel(ParametersPanel parametersPanel, ControlsPanel controlPanel) {            
        this.parametersPanel = parametersPanel;
        this.controlsPanel = controlPanel;          
        startIsPressed = controlsPanel.StartisPressed();            
        this.setBackground(new Color(237,237,237));
        this.setLayout(null);           
        CashRegister cashRegister = new CashRegister();
        img = cashRegister.getImg();            
        amount = parametersPanel.getAmountOfRegisters();            
    }

    //Painting CashRegisters
    public void paintComponent(Graphics g) {

        if(startIsPressed) {        
        super.paintComponent(g);
        for (int i = 1; i <= amount; i++) {
            g.drawImage(img, 30, i*50, this);
        }
        }
    }
}

【问题讨论】:

    标签: java swing paintcomponent


    【解决方案1】:

    您的问题可以简单地归结为:当发生更改时,如何将一个类通知另一个类的状态更改。这是事件驱动的 GUI 程序(以及其他程序类型)中的常见问题,也是开发观察者或侦听器类型设计模式的全部原因。所以我的建议就是,你以某种方式使用监听器设计模式。这可以通过多种方式实现,包括:

    • 允许一个类将 ActionListener 附加到第一个类的 JButton
    • 让观察者 cla 添加某种类型的侦听器到更改状态的类,即具有 JButton 的类
    • 或者我最喜欢的:将布尔值完全从视图类中取出并放入模型类中,并让任何想要通知的视图注册模型的侦听器并根据需要对模型状态的更改做出反应。我经常使用后者,经常使用 PropertyChangeListeners 来实现这一点。

    所以模型类可能看起来像:

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

    编辑 例如,这是一个 M-V 或 Model-View 简单示例程序:

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

    是的,对于您非常简单的情况,这可能有点过头了,但它可以很好地扩展,因为您可以将模型和 GUI 关注点分开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-03
      • 1970-01-01
      • 2017-08-19
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 2019-02-09
      • 2021-03-21
      相关资源
      最近更新 更多