有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java观察者模式同时更新文本字段和条形图

所以我正在做一个观察者模式分配。我有两个窗口,每个窗口有4个字段。在一个窗口中,您可以在4个不同的文本框中键入双值,它们会反映在条形图中4个相应的条形图中

我还可以通过按下鼠标按钮来更改条形图中的条形图,它会移动到指针所在的位置。现在,我也想更新文本字段,但我不知道该怎么做。它似乎收到了一个通知,说明已经发生了变化,但我不知道如何在字段中设置适当的文本。吧台架重新喷漆了。我对文本框也这么做吗

以下是我迄今为止的3个相关类的代码:

酒吧架

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

}

}

数据模型

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

   }

}

文本框

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

}


}

以下是几条注释: 我知道,如果你用maxed值来改变条的值(其他条会移动),那就有问题了。这是我应该扩展的代码。我猜是这样的,这样就可以用作参考点。 我知道我可以通过使用适配器摆脱不必要的鼠标侦听器,但我的指令将它们声明为空

如果有人想回答这个问题,还有一个额外的问题:有没有办法在我的鼠标按下时获得实际的双精度?它总是返回一个整数

总之,很抱歉发了这么长的帖子。提前感谢您的帮助


共 (1) 个答案

  1. # 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
       }