2016-10-20 7 views
2

JFreeChartの場合、JPanelを拡張するクラスがあります。 setMean()の内部では、datasetまたはFunction2Dの値を更新しようとしましたが、repaint()であってもグラフ上で何も変わりません。JFreeChartでJTextFieldを使用して正規分布グラフを更新します。

public class JFreeChartPanel extends JPanel { 
     Function2D normal = new NormalDistributionFunction2D(0.0, 3.0); 
     XYDataset dataset = DatasetUtilities.sampleFunction2D(normal, -5.0, 5.0, 100, "Normal"); 

     double mean = 0.0, std = 1.0; 

     public double getMean() { 
      return mean; 
     } 

     public void setMean(double mean) { 
      this.mean = mean; 
      normal = new NormalDistributionFunction2D(mean,std); 
      dataset = DatasetUtilities.sampleFunction2D(normal, -5.0, 5.0, 100, "Normal"); 
      repaint(); 
     } 

     public double getStd() { 
      return std; 
     } 

     public void setStd(double std) { 
      this.std = std; 
     } 

     public JFreeChartPanel(){   

      JFreeChart chart = ChartFactory.createXYLineChart(
       "Normal Distribution", 
       "X", 
       "Y", 
       dataset, 
       PlotOrientation.VERTICAL, 
       true, 
       true, 
       false 
      ); 


      final ChartPanel chartPanel = new ChartPanel(chart); 
      setLayout(new BorderLayout()); 
      add(chartPanel); 
     } 
} 

これは私のJTextFieldの値を変更するたびに実行されます。

public void updateMean() 
    { 
     String meanS = mean.getText(); 
     double mean = 0.0; 
     try{ 
      mean = Double.parseDouble(meanS); 
      System.out.println("Mean: "+mean); 
      jFreeChartPanel.setMean(mean); 
     }catch(Exception e){ 
      System.out.println("Mean: incorrect input"); 
     } 
    } 
+0

あなたは、データセットが保持している値を変更していますがはJFreeChartチャートを変更することはありません、魔法のように自身で変更するつもりはありません。私はJFreeChartを使用しませんが、表示されたチャートのメソッドを呼び出すことができるかどうか、または新しいデータで新しいメソッドを作成する必要があるかどうかをAPIで確認する必要があります。 –

+0

@HovercraftFullOfEels私が読んだ限り、JFreeChartにはたくさんのリスナーがありますので、変更は自動的にグラフに反映されるはずです。 – Higeath

+0

リスナーの仕組みを理解していない - 設定する必要があります。リスナーを機能させるために配線してください。はい、データセットオブジェクトを使用してJFreeChartオブジェクトを作成しますが、データセットを後で変更するだけでJFreeChartオブジェクトには影響しません。 JFreeChartオブジェクトには*モデル*があり、このモデルにリスナーがあり、適切なセッターメソッド、つまりリスナーを移動するメソッドを使用してモデルを変更すると、私はあなたの期待を理解することができました。まったく新しいデータセットオブジェクトを作成しているので、想定している通りに動作するとは限りません。 –

答えて

4

通常、あなたは単にJFreeChartを作成するために使用されるXYDatasetを更新でき、リスニングチャートは対応して自分自身を更新します。 @Hovercraft notesのように、repaint()だけでは、データセットに置き換えられていることをグラフのプロットに伝えるには不十分です。下の例では、データセットの初期化をリファクタリングし、パラメータとしてsetDataset()に渡しました。

public void setMean(double mean) { 
    this.mean = mean; 
    plot.setDataset(initDataset()); 
} 

イベントワイヤリングを調べるには、該当するsourceを参照してください。 JSpinnerChangeListenerを追加すると、JTextFieldより操作しやすくなる可能性があります。

image

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSpinner; 
import javax.swing.event.ChangeEvent; 
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.plot.PlotOrientation; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.data.function.Function2D; 
import org.jfree.data.function.NormalDistributionFunction2D; 
import org.jfree.data.general.DatasetUtilities; 
import org.jfree.data.xy.XYDataset; 

/** 
* @see https://stackoverflow.com/a/40167139/230513 
*/ 
public class TestDistribution { 

    private static class JFreeChartPanel extends JPanel { 

     private XYPlot plot; 
     private double mean = 0.0, sigma = 1.0; 
     XYDataset dataset = initDataset(); 

     private XYDataset initDataset() { 
      Function2D normal = new NormalDistributionFunction2D(mean, sigma); 
      XYDataset dataset = DatasetUtilities.sampleFunction2D(normal, -5.0, 5.0, 100, "Normal"); 
      return dataset; 
     } 

     ; 
     public double getMean() { 
      return mean; 
     } 

     public void setMean(double mean) { 
      this.mean = mean; 
      plot.setDataset(initDataset()); 
     } 

     public double getStd() { 
      return sigma; 
     } 

     public void setStd(double sigma) { 
      this.sigma = sigma; 
     } 

     public JFreeChartPanel() { 
      JFreeChart chart = ChartFactory.createXYLineChart(
       "Normal Distribution", "X", "Y", dataset, 
       PlotOrientation.VERTICAL, true, true, false 
      ); 
      plot = chart.getXYPlot(); 
      final ChartPanel chartPanel = new ChartPanel(chart); 
      add(chartPanel); 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("TestDistribution"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JFreeChartPanel chartPanel = new JFreeChartPanel(); 
     f.add(chartPanel); 
     JSpinner spinner = new JSpinner(); 
     spinner.setValue(chartPanel.mean); 
     spinner.addChangeListener((ChangeEvent e) -> { 
      JSpinner s = (JSpinner) e.getSource(); 
      Number n = (Number) s.getValue(); 
      chartPanel.setMean(n.doubleValue()); 
     }); 
     f.add(spinner, BorderLayout.PAGE_END); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new TestDistribution()::display); 
    } 
} 
+0

関連するイベントチェーンが検討されています[ここ](http://stackoverflow.com/a/6206616/230513)。 – trashgod

+0

もしあなたが気にしないのであれば、x軸のtickUnitsを簡単に変更する方法はありますか? NumberAxisの代わりにValueAxisを使用しているので、setTickUnitにアクセスできません。 – Higeath

+0

'ChartFactory.createXYLineChart()'は内部的に 'NumberAxis'を使用します。新しい質問が検討されている[ここ](http://stackoverflow.com/q/40184461/230513)。 – trashgod

関連する問題