2017-03-05 64 views
1

我正在嘗試在Java中創建條形圖。JFreeChart的條形圖欄單元

我想在DateAxis(不是打勾單位)上有1H條形單位。有沒有辦法? 經過大量的谷歌搜索,我還沒有發現任何有趣的事情。

這就是我得到:

BarChart

ChartAdapter.java

public class ChartAdapter extends JFrame { 

/** 
* Constructs the demo application. 
* 
* @param title the frame title. 
*/ 
public ChartPanel generateChart(String title, Vector<Vector<String>> dataVector) { 
    JFreeChart chart = ChartFactory.createXYBarChart(
     title, 
     "X", 
     true, 
     "Y", 
     createDataset(dataVector), 
     PlotOrientation.VERTICAL, 
     true, 
     false, 
     false 
    ); 


    final XYItemRenderer renderer = chart.getXYPlot().getRenderer(); 
    final StandardXYToolTipGenerator generator = new StandardXYToolTipGenerator(
     "{1} = {2}", new SimpleDateFormat("yyyy"), new DecimalFormat("0.00") 
    ); 
    renderer.setToolTipGenerator(generator); 

    final XYPlot plot = chart.getXYPlot(); 
    final DateAxis dAxis = (DateAxis) plot.getDomainAxis(); 
    dAxis.setVerticalTickLabels(true); 
    final NumberAxis nAxis = (NumberAxis) plot.getRangeAxis(); 

    Calendar c = Calendar.getInstance(); 
    c.setTime(dAxis.getMinimumDate()); 
    c.add(Calendar.HOUR, 12); 

    final ChartPanel chartPanel = new ChartPanel(chart); 
    chartPanel.setPreferredSize(new java.awt.Dimension(600, 300)); 


    return chartPanel; 
} 

private IntervalXYDataset createDataset(Vector<Vector<String>> dataVector) { 
    TimeSeries series = new TimeSeries("Value"); 

    for(Vector<String> tempVector : dataVector) { 
     Timestamp time = Timestamp.valueOf(tempVector.get(0)); 
     series.add(new Millisecond(time), Double.parseDouble(tempVector.get(1))); 
    } 
    TimeSeriesCollection dataset = new TimeSeriesCollection(series); 
    dataset.setDomainIsPointsInTime(false); 
     return dataset; 
    } 
} 

Test.java

public class Test extends JFrame { 

    private JPanel contentPane; 
    Vector<Vector<String>> dataVector = new Vector<Vector<String>>(); 

    /** 
    * Launch the application. 
    */ 
    public static void main(String[] args) { 



     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        Test frame = new Test(); 
        frame.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    /** 
    * Create the frame. 
    */ 
    public Test() { 
     Vector<String> tempString = null; 

     Calendar c = Calendar.getInstance(); 
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 
     try { 
      c.setTime(sdf.parse("2017-01-12 12:00:00")); 
     } catch (ParseException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     for(int i=0; i<10; i++) { 
      tempString = new Vector<String>(); 
      tempString.add(sdf.format(c.getTime())); 
      tempString.add(String.valueOf((int)(Math.random()*35))); 
      c.add(Calendar.HOUR, 1); 
      dataVector.add(tempString); 
     } 




     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setBounds(100, 100, 450, 300); 
     contentPane = new JPanel(); 
     contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
     setContentPane(contentPane); 
     //contentPane.add(chart.generateChart(chart.getMinValue(), chart.getMaxValue())); 
     contentPane.add(new ChartAdapter().generateChart("Data", dataVector)); 
     contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); 
    } 

} 

回答

1

我已經簡化你的例子將重點放在組成數據集的時間間隔上。使用一個Calendar.HOUR的間隔確保條形顯示一個小時的寬度。雖然你的問題具體避開剔單位,某些功能可能前進有用:

  • 使用here所示的方法來獲取特定週期的時間間隔。

    domainAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR, 1)); 
    
  • 使用setTickMarkPosition()居中在所選擇的時間間隔的刻度線。

    domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE); 
    

image

import java.awt.EventQueue; 
import java.text.DecimalFormat; 
import java.text.SimpleDateFormat; 
import java.util.Calendar; 
import java.util.Random; 
import javax.swing.JFrame; 
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.axis.DateAxis; 
import org.jfree.chart.axis.DateTickMarkPosition; 
import org.jfree.chart.axis.DateTickUnit; 
import org.jfree.chart.axis.DateTickUnitType; 
import org.jfree.chart.labels.StandardXYToolTipGenerator; 
import org.jfree.chart.plot.PlotOrientation; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.chart.renderer.xy.XYItemRenderer; 
import org.jfree.data.time.Hour; 
import org.jfree.data.time.TimeSeries; 
import org.jfree.data.time.TimeSeriesCollection; 
import org.jfree.data.xy.IntervalXYDataset; 

/** @see https://stackoverflow.com/a/42612723/230513 */ 
public class Test { 

    public static void main(String[] args) { 

     EventQueue.invokeLater(() -> { 
      Test frame = new Test(); 
     }); 
    } 

    public Test() { 
     JFrame f = new JFrame("Data"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new ChartAdapter().generateChart("Data")); 
     f.pack(); 
     f.setVisible(true); 
    } 

    class ChartAdapter { 

     public ChartPanel generateChart(String title) { 
      JFreeChart chart = ChartFactory.createXYBarChart(
       title, "Time", true, "Value", createDataset(), 
       PlotOrientation.VERTICAL, true, false, false 
      ); 
      final XYItemRenderer renderer = chart.getXYPlot().getRenderer(); 
      final StandardXYToolTipGenerator generator = new StandardXYToolTipGenerator(
       "{1} : {2}", new SimpleDateFormat("HH:mm"), new DecimalFormat("0.00") 
      ); 
      renderer.setBaseToolTipGenerator(generator); 
      final XYPlot plot = chart.getXYPlot(); 
      final DateAxis domainAxis = (DateAxis) plot.getDomainAxis(); 
      domainAxis.setVerticalTickLabels(true); 
      domainAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR, 1)); 
      domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE); 
      domainAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm")); 
      return new ChartPanel(chart); 
     } 

     private IntervalXYDataset createDataset() { 
      Random r = new Random(); 
      TimeSeries series = new TimeSeries("Value"); 
      Calendar c = Calendar.getInstance(); 
      for (int i = 0; i < 10; i++) { 
       series.add(new Hour(c.getTime()), r.nextGaussian() + 7); 
       c.add(Calendar.HOUR, 1); 
      } 
      return new TimeSeriesCollection(series); 
     } 
    } 
} 
+0

非常感謝您的幫助!這正是我的意思!我試過沒有結果的tickunit,我認爲tickunit是用於標籤間隔範圍的。也許我錯過了一些東西。 – wuase

+0

@wuase:很高興幫助。我也會盡量避免將'Date'轉換爲'String'直到需要顯示。 – trashgod