2015-04-05 40 views
0

所以我正在研究觀察員模式分配。我有2個窗口,每個窗口有4個字段。在一個窗口中,您可以將雙值輸入到4個不同的文本框中,並且它們會反映在條形圖中的4個對應條之一中。觀察者模式更新文本字段和條形圖

我也可以通過按下鼠標按鈕來更改條形圖中的條形圖,並將其移動到指針所在的位置。現在,我想要更新文本字段,但我不知道如何執行此操作。它似乎得到一個通知,說有變化,但我不知道如何在現場設置適當的文本。酒吧框架重新繪製。我是否也爲文本框架執行此操作?

這裏是我的3分相關的類代碼至今:

BarFrame

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.geom.*; 

import javax.swing.*; 
import javax.swing.event.*; 

import java.util.*; 

/** 
    A class that implements an Observer object that displays a barchart view of 
    a data model. 
*/ 
public class BarFrame extends JFrame implements ChangeListener, MouseListener 
{ 

     private ArrayList<Double> a; 
     private DataModel dataModel; 

     private static final int ICON_WIDTH = 200; 
     private static final int ICON_HEIGHT = 200; 
    /** 
     Constructs a BarFrame object 
     @param dataModel the data that is displayed in the barchart 
    */ 
    public BarFrame(DataModel dataModel) 
    { 
     this.dataModel = dataModel; 
     a = dataModel.getData(); 

     setLocation(0,200); 
     setLayout(new BorderLayout()); 

     addMouseListener(this); // adds the mouse listener in to the bar frame 

     Icon barIcon = new Icon() 

     { 
     public int getIconWidth() { return ICON_WIDTH; } 
     public int getIconHeight() { return ICON_HEIGHT; } 

     public void paintIcon(Component c, Graphics g, int x, int y) 
     { 
      Graphics2D g2 = (Graphics2D) g; 

      g2.setColor(Color.red); 

      double max = (a.get(0)).doubleValue(); 

      for (Double v : a) 
      { 
       double val = v.doubleValue(); 
       if (val > max) 
        max = val; 
      } 
      double barHeight = getIconHeight()/a.size(); 

      int i = 0; 
      for (Double v : a) 
      { 
       double value = v.doubleValue(); 

       double barLength = getIconWidth() * value/max; 
       Rectangle2D.Double rectangle = new Rectangle2D.Double 
        (0, barHeight * i, barLength, barHeight); 
       i++; 
       g2.fill(rectangle); 
      } 
     } 
     }; 

     add(new JLabel(barIcon)); 

     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
    } 

    /** 
     Called when the data in the model is changed. 
     @param e the event representing the change 
    */ 
    public void stateChanged(ChangeEvent e) 
    { 
     a = dataModel.getData(); 
//  for(Double d: a){ 
//  System.out.println(d); 
//  } 
     repaint(); 
    } 


@Override 
public void mouseClicked(MouseEvent e) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void mousePressed(MouseEvent e) { 
    // TODO Auto-generated method stub 

    double max = Collections.max(dataModel.getData()); 
    double value = (double)e.getX()/(double)getWidth()* max; 

    if(30 <= e.getY() && e.getY() < 80){ 
     //first bar 
     dataModel.update(0, value); 
    } 

    if(80 <= e.getY() && e.getY() < 130){ 
     //second bar 
     dataModel.update(1, value); 
    } 

    if(130 <= e.getY() && e.getY() < 180){ 
     //third bar 
     dataModel.update(2, value); 
    } 

    if(180 <= e.getY() && e.getY() < 230){ 
     //fourth bar 
     dataModel.update(3, value); 
    } 
} 

@Override 
public void mouseReleased(MouseEvent e) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void mouseEntered(MouseEvent e) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void mouseExited(MouseEvent e) { 
    // TODO Auto-generated method stub 

} 

} 

的DataModel

import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.util.ArrayList; 

import javax.swing.event.*; 

/** 
    A Subject class for the observer pattern. 
*/ 
public class DataModel 
{ 
     ArrayList<Double> data; 
     ArrayList<ChangeListener> listeners; 

    /** 
     Constructs a DataModel object 
     @param d the data to model 
    */ 
    public DataModel(ArrayList<Double> d) 
    { 
     data = d; 
     listeners = new ArrayList<ChangeListener>(); 

    } 

    /** 
     Constructs a DataModel object 
     @return the data in an ArrayList 
    */ 
    @SuppressWarnings("unchecked") 
public ArrayList<Double> getData() 
    { 
     return (ArrayList<Double>) (data.clone()); 
    } 

    /** 
     Attach a listener to the Model 
     @param c the listener 
    */ 
    public void attach(ChangeListener c) 
    { 
     listeners.add(c); 
    } 

    /** 
     Change the data in the model at a particular location 
     @param location the index of the field to change 
     @param value the new value 
    */ 
    public void update(int location, double value) 
    { 
     data.set(location, new Double(value)); 
    // frame.fieldList[location].setText(Double.toString(value)); 
     for (ChangeListener l : listeners) 
     { 
//  System.out.println("l = " + l); 
     l.stateChanged(new ChangeEvent(this)); 
     } 

    } 

} 

TextFrame

import java.awt.*; 
import java.awt.event.*; 

import javax.swing.*; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

import java.util.ArrayList; 

/** 
    A class for displaying the model as a column of textfields in a frame. 
*/ 
public class TextFrame extends JFrame implements ChangeListener 
{ 

     DataModel dataModel; 
     JTextField[] fieldList; 
     private ArrayList<Double> a; 
    /** 
     Constructs a JFrame that contains the textfields containing the data 
     in the model. 
     @param d the model to display 
    */ 
    public TextFrame(DataModel d) 
    { 
     dataModel = d; 

     final Container contentPane = this.getContentPane(); 
     setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 

     ArrayList<Double> a = dataModel.getData(); 
     fieldList = new JTextField[a.size()]; 

     // A listener for action events in the text fields 
     ActionListener l = new ActionListener() 
     { 
     public void actionPerformed(ActionEvent e) 
     { 
      // Figure out which field generated the event 
      JTextField c = (JTextField) e.getSource(); 
      int i = 0; 
      int count = fieldList.length; 
      while (i < count && fieldList[i] != c) 
       i++; 

      String text = c.getText().trim(); 

      try 
      { 
       double value = Double.parseDouble(text); 
       dataModel.update(i, value); 
      } 
      catch (Exception exc) 
      { 
       c.setText("Error. No update"); 
      } 
     } 
     }; 

     final int FIELD_WIDTH = 11; 
     for (int i = 0; i < a.size(); i++) 
     { 
     JTextField textField = new JTextField(a.get(i).toString(),FIELD_WIDTH); 
     textField.addActionListener(l); 
     add(textField); 
     fieldList[i] = textField; 
     } 

     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
    } 


    /** 
    Called when the data in the model is changed. 
    @param e the event representing the change 
*/ 
public void stateChanged(ChangeEvent e) 
{ 
    a = dataModel.getData(); 
// for(Double d: a){ 
// System.out.println(d); 
// } 

} 


} 

一對夫婦的注意事項: 我知道,如果用最大值更改了欄的值(其他欄移動),那麼它就很有問題了。隨着我應該延續的代碼出現了。我猜是這樣,以便它可以用作參考點。 我知道我可以通過使用適配器擺脫不必要的鼠標偵聽器,但是我的指令聲明將它們實現爲空。

獎金的問題,如果有人覺得回答:有沒有辦法讓我的鼠標按下實際雙精度?它總是返回一個整數。

無論如何,對不起,很長的職位。提前謝謝你的幫助!

回答

1

想通了! 我在TextFrame的stateChanged方法中添加了以下內容:

for(int i = 0; i < a.size(); i++){ 
     fieldList[i].setText(Double.toString(Math.round(a.get(i) * 10)/10.0)); // to get 1 decimal place accuracy 
    }