2015-06-02 19 views
1

我試圖讓一個MVC的Java Swing的程序使用SwingPropertyChangeSupport的通知每當模型被更新的觀點。我遇到的問題是通知似乎沒有發生。的Java:SwingPropertyChangeSupport

我已經準備下面的SSCCE。在SSCCE中,有一個Swing GUI,它有一個按鈕和一個文本字段。當你點擊按鈕時,模型中的一個計數器會增加,並且該視圖應該被通知,以便它可以自我更新。但是,即使我已經檢查確保oldValue和newValue彼此不同,但它似乎並沒有發送/接收通知(我不確定哪些 - 它可能都是)。我很感謝任何幫助,以瞭解我出錯的地方。謝謝!

import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

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 Main extends JFrame { 

    public Main() { 
     PropertyChangeView theGui = new PropertyChangeView(); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setResizable(true); 
     add(theGui); 
     pack(); 
     setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       new Main(); 
      } 
     }); 
    } 
} 


class PropertyChangeView extends JPanel { 
    private JButton button; 
    private JTextField textfield; 
    private GridBagConstraints gbc; 
    private PropertyChangeController controller; 

    public PropertyChangeView() { 
     super(new GridBagLayout()); 
     controller = new PropertyChangeController(); 
     button = new JButton("Click me to increment the count"); 
     textfield = new JTextField(10); 

     button.addActionListener(new ButtonListener()); 
     addPropertyChangeListener(new MyPropertyChangeListener()); 

     gbc = new GridBagConstraints(); 
     gbc.gridheight = 1; 
     gbc.gridwidth = 1; 
     gbc.anchor = GridBagConstraints.LINE_START; 
     gbc.fill = GridBagConstraints.BOTH; 

     gbc.gridx = 0; 
     gbc.gridy = 0; 
     add(button, gbc); 

     gbc.gridx = 1; 
     gbc.gridy = 0; 
     add(textfield, gbc); 
    } 

    private class MyPropertyChangeListener implements PropertyChangeListener { 
     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
      System.out.println("Event received " + evt); 

      if (evt.getPropertyName().equals(PropertyChangeModel.CHANGED)) { 
       textfield.setText(evt.getNewValue().toString()); 
      } 
     } 
    } 

    private class ButtonListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      controller.setCounter(controller.getCounter() + 1); 
      System.out.println("counter now = " + controller.getCounter()); 
     } 
    } 

} 


class PropertyChangeController { 
    private PropertyChangeModel model; 

    public PropertyChangeController() { 
     model = new PropertyChangeModel(); 
    } 

    public int getCounter() { 
     return model.getCounter(); 
    } 

    public void setCounter(int i) { 
     model.setCounter(i); 
    } 
} 


class PropertyChangeModel { 
    public static final String CHANGED = "property change model updated"; 

    private int counter; 
    private SwingPropertyChangeSupport pcs; 

    public PropertyChangeModel() { 
     counter = 0; 
     pcs = new SwingPropertyChangeSupport(this); 
    } 

    public int getCounter() { 
     return counter; 
    } 

    public void setCounter(int i) { 
     int oldValue = counter; 
     int newValue = i; 
     counter = newValue; 
     pcs.firePropertyChange(CHANGED, oldValue, newValue); 
     System.out.println("setCounter finished with oldValue=" + oldValue + ", newValue=" + newValue); 
    } 
} 

回答

3

我沒有運行您的程序,但我在這裏看到一個東西出來的順序:

public void setCounter(int i) { 
    int oldValue = counter; 
    int newValue = i; 
    pcs.firePropertyChange(CHANGED, oldValue, newValue); 
    counter = newValue; 
    System.out.println("setCounter finished with oldValue=" + oldValue + ", newValue=" + newValue); 
} 

這應該是:

public void setCounter(int i) { 
    int oldValue = counter; 
    int newValue = i; 
    counter = newValue; 
    pcs.firePropertyChange(CHANGED, oldValue, newValue); 
    System.out.println("setCounter finished with oldValue=" + oldValue + ", newValue=" + newValue); 
} 

你應該解僱通知後僅更新模型的值。

你的主要問題是,雖然你沒有的PropertyChangeListener添加到模型。


例如,

import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

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 Main extends JFrame { 

    public Main() { 
     PropertyChangeView theGui = new PropertyChangeView(); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setResizable(true); 
     add(theGui); 
     pack(); 
     setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      new Main(); 
     } 
     }); 
    } 
} 

class PropertyChangeView extends JPanel { 
    private JButton button; 
    private JTextField textfield; 
    private GridBagConstraints gbc; 
    private PropertyChangeController controller; 

    public PropertyChangeView() { 
     super(new GridBagLayout()); 
     PropertyChangeModel model = new PropertyChangeModel(); 
     controller = new PropertyChangeController(model); 
     button = new JButton("Click me to increment the count"); 
     textfield = new JTextField(10); 

     button.addActionListener(new ButtonListener()); 
     model.addPropertyChangeListener(new MyPropertyChangeListener()); 


     gbc = new GridBagConstraints(); 
     gbc.gridheight = 1; 
     gbc.gridwidth = 1; 
     gbc.anchor = GridBagConstraints.LINE_START; 
     gbc.fill = GridBagConstraints.BOTH; 

     gbc.gridx = 0; 
     gbc.gridy = 0; 
     add(button, gbc); 

     gbc.gridx = 1; 
     gbc.gridy = 0; 
     add(textfield, gbc); 
    } 

    private class MyPropertyChangeListener implements PropertyChangeListener { 
     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
     System.out.println("Event received " + evt); 

     if (evt.getPropertyName().equals(PropertyChangeModel.CHANGED)) { 
      textfield.setText(evt.getNewValue().toString()); 
     } 
     } 
    } 

    private class ButtonListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
     controller.setCounter(controller.getCounter() + 1); 
     System.out.println("counter now = " + controller.getCounter()); 
     } 
    } 

} 

class PropertyChangeController { 
    private PropertyChangeModel model; 

    // public PropertyChangeController() { 
    // model = new PropertyChangeModel(); 
    // } 


    public PropertyChangeController(PropertyChangeModel model) { 
     this.model = model; 
    } 

    public int getCounter() { 
     return model.getCounter(); 
    } 


    public void setCounter(int i) { 
     model.setCounter(i); 
    } 
} 

class PropertyChangeModel { 
    public static final String CHANGED = "property change model updated"; 

    private int counter; 
    private SwingPropertyChangeSupport pcs; 

    public PropertyChangeModel() { 
     counter = 0; 
     pcs = new SwingPropertyChangeSupport(this); 
    } 

    public void addPropertyChangeListener(
     PropertyChangeListener l) { 
     pcs.addPropertyChangeListener(l); 
    } 

    public int getCounter() { 
     return counter; 
    } 

    public void setCounter(int i) { 
     int oldValue = counter; 
     int newValue = i; 
     counter = newValue; 
     pcs.firePropertyChange(CHANGED, oldValue, newValue); 
     System.out.println("setCounter finished with oldValue=" + oldValue 
      + ", newValue=" + newValue); 
    } 
} 
+0

謝謝,我已更新代碼示例,在觸發通知之前放置'counter = newValue'。至於PropertyChangeListener,我在視圖中添加了一個,因爲這是我想要通知的。那是不正確的? (我想這一定是因爲我的程序不能正常工作!) – user1002119

+0

@ user1002119:你已經倒過來了。您將偵聽器添加到您正在偵聽的項目 - 模型。你的監聽器會通知視圖。請參閱上面代碼的更改。 –

+0

@ user1002119:雖然我會盡我創作的單一控制/模型和視圖和一個單獨的類內掛鉤起來的,但回答(我得去上班)的速度我沒有做這個大的更改爲您的代碼。 –

相關問題