2016-10-20 53 views
2

我有一個類JPanelJFreeChart。在setMean()的內部,我嘗試更新datasetFunction2D的值,但即使使用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對象有一個* model *,如果這個模型有偵聽器,並且使用適當的setter方法修改模型,那麼偵聽器的方法就可以理解你的期望,但是你沒有。您正在創建一個全新的數據集對象,因此您無法按照您的設想工作。 –

回答

4

通常情況下,你可以簡單地更新用於創建JFreeChartXYDataset,並聆聽圖表將響應更新自己。由於@Hovercraft notes,repaint()單獨不足以告訴圖表的情節,您已將替換爲數據集。在下面的例子中,我重構了數據集的初始化並將其作爲參數傳遞給setDataset()

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

請參閱相關source來檢查事件接線。 A ChangeListener加入到JSpinner可能比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?由於它使用的是ValueAxis而不是NumberAxis,因此我無法訪問setTickUnit – Higeath

+0

'ChartFactory.createXYLineChart()'在內部使用'NumberAxis',因此您可以投射;新問題將在[這裏](http://stackoverflow.com/q/40184461/230513)中進行介紹。 – trashgod