Вопрос

I'm trying to generate a task scheduler chart using Gantt Chart , but encountered some problems. How can the X axis displaye as numbers instead of dates. is there any way to write a functhion TaskWhatIWant(String , int ,int) instead of Task(String ,data,data) to generate a task scheduler like Gantt

what it is now

enter image description here

what i want is

enter image description here

Or is there a better way to generate a task scheduling chart like this any help will be appreciated.

package plugtest;

import java.awt.Color;
import java.awt.Dimension;
import java.util.Calendar;
import java.util.Date;

import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.data.category.IntervalCategoryDataset;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;


public class GanttDemo extends ApplicationFrame
{

   public GanttDemo(String s)
   {
      super(s);
      JPanel jpanel = createDemoPanel();
      jpanel.setPreferredSize(new Dimension(500, 270));
      setContentPane(jpanel);
   }

   private static JFreeChart createChart(IntervalCategoryDataset intervalcategorydataset)
   {
      JFreeChart jfreechart = ChartFactory.createGanttChart("Gantt Chart Demo", "Task", "Date", intervalcategorydataset, true, true, false);
      CategoryPlot categoryplot = (CategoryPlot)jfreechart.getPlot();
      categoryplot.setRangePannable(true);
      categoryplot.getDomainAxis().setMaximumCategoryLabelWidthRatio(10F);
      CategoryItemRenderer categoryitemrenderer = categoryplot.getRenderer();
      categoryitemrenderer.setSeriesPaint(0, Color.blue);
      return jfreechart;
   }

   private static IntervalCategoryDataset createDataset()
   {
      TaskSeries taskseries = new TaskSeries("Scheduled");
      /*  which i want it to be 
      *    **Task' task'=new Task'(String taskName, int start,int end);** 
      */ 
      Task task = new Task("task1", date(1, 3, 2001), date(5, 3, 2001));    
      task.setPercentComplete(1.0D);
      taskseries.add(task);
      Task task1 = new Task("task2", date(9, 3, 2001), date(11, 5, 2001));
      taskseries.add(task1);
      Task task2 = new Task("task3", date(10, 3, 2001), date(5, 4, 2001));
      taskseries.add(task2);

      TaskSeriesCollection taskseriescollection = new TaskSeriesCollection();
      taskseriescollection.add(taskseries);
      return taskseriescollection;
   }

   private static Date date(int i, int j, int k)
   {
      Calendar calendar = Calendar.getInstance();
      calendar.set(k, j, i);
      Date date1 = calendar.getTime();
      return date1;
   }

   public static JPanel createDemoPanel()
   {
      JFreeChart jfreechart = createChart(createDataset());
      ChartPanel chartpanel = new ChartPanel(jfreechart);
      chartpanel.setMouseWheelEnabled(true);
      return chartpanel;
   }

   public static void main(String args[])
   {
      GanttDemo ganttdemo = new GanttDemo("gantt demo");
      ganttdemo.pack();
      RefineryUtilities.centerFrameOnScreen(ganttdemo);
      ganttdemo.setVisible(true);
   }
}

Thanks @Baz for the suggestion.

Here is the sulotion and the demo

modified function createGanttChart:

public static JFreeChart createGanttChart(String title, 
                      String categoryAxisLabel,
                      String dateAxisLabel, 
                      IntervalCategoryDataset dataset, 
                      boolean legend,            
                      boolean tooltips,     
                      boolean urls) {

        CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel);
        ValueAxis dateAxis = new NumberAxis(dateAxisLabel);//important,change axis from data to value

        CategoryItemRenderer renderer = new GanttRenderer();
        if (tooltips) {
            renderer.setBaseToolTipGenerator(
                    (CategoryToolTipGenerator) new IntervalCategoryToolTipGenerator(
                            "{1}Schedule Time: {3}ms - {4}ms", NumberFormat .getNumberInstance()));
            }
        if (urls) {
                    renderer.setBaseItemURLGenerator(
                    new StandardCategoryURLGenerator());
            }
        CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, dateAxis, 
                    renderer);
        plot.setOrientation(PlotOrientation.HORIZONTAL);
        JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
        plot, legend);

        return chart;

 }

}

modified class Task

 package plugtest;

 import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
 import org.jfree.data.time.SimpleTimePeriod;
 import org.jfree.data.time.TimePeriod;
 import org.jfree.util.ObjectUtilities;
 import org.jfree.util.PublicCloneable;


 public class Task implements Cloneable, PublicCloneable, Serializable {

 /** For serialization. */
 private static final long serialVersionUID = 1094303785346988894L;


 private String description;


 private double start; //start Time

 private double end;   //end Time

 public double getStart() {
        return start;
    }

 public void setStart(double start) {
        this.start = start;
    }

 public double getEnd() {
        return end;
    }

 public void setEnd(double end) {
    this.end = end;
    }

 /** The percent complete (<code>null</code> is permitted). */
private Double percentComplete;

 /** Storage for the sub-tasks (if any). */
 private List subtasks;


 public Task(String description, double start , double end) {
     if (description == null) {
         throw new IllegalArgumentException("Null 'description' argument.");
     }
     this.description = description;
     this.start=start;
     this.end=end;
     this.percentComplete = null;
     this.subtasks = new java.util.ArrayList();
 }



 public String getDescription() {
     return this.description;
 }

 public void setDescription(String description) {
     if (description == null) {
         throw new IllegalArgumentException("Null 'description' argument.");
     }
     this.description = description;
 }


 public Double getPercentComplete() {
     return this.percentComplete;
 }


 public void setPercentComplete(Double percent) {
     this.percentComplete = percent;
 }


 public void setPercentComplete(double percent) {
     setPercentComplete(new Double(percent));
 }


 public void addSubtask(Task subtask) {
     if (subtask == null) {
         throw new IllegalArgumentException("Null 'subtask' argument.");
     }
     this.subtasks.add(subtask);
 }


 public void removeSubtask(Task subtask) {
     this.subtasks.remove(subtask);
 }


 public int getSubtaskCount() {
     return this.subtasks.size();
 }


 public Task getSubtask(int index) {
     return (Task) this.subtasks.get(index);
 }


 public boolean equals(Object object) {
     if (object == this) {
         return true;
     }
     if (!(object instanceof Task)) {
         return false;
     }
     Task that = (Task) object;
     if (!ObjectUtilities.equal(this.description, that.description)) {
         return false;
     }
     if (!ObjectUtilities.equal(this.start, that.start)) {
         return false;
     }
     if (!ObjectUtilities.equal(this.end, that.end)) {
         return false;
     }
     if (!ObjectUtilities.equal(this.percentComplete, 
             that.percentComplete)) {
         return false;
     }
     if (!ObjectUtilities.equal(this.subtasks, that.subtasks)) {
         return false;
     }
     return true;
 }


 public Object clone() throws CloneNotSupportedException {
     Task clone = (Task) super.clone();
     return clone;      
 }


 }

modified function getStartValue(Comparable,Comparable), getEndValue(Comparable,Comparable),getStartValue(Comparable,Comparable,int),getEndValue(Comparable,Comparable,int)in class TaskSeriesCollection.

 public Number getStartValue(Comparable rowKey, Comparable columnKey) {
     Number result = null;
     int row = getRowIndex(rowKey);
     TaskSeries series = (TaskSeries) this.data.get(row);
     Task task = series.get(columnKey.toString());
     if (task != null) {
        result = task.getStart(); //return the start time of task

     }
     return result;
 }
public Number getEndValue(Comparable rowKey, Comparable columnKey) {
     Number result = null;
     int row = getRowIndex(rowKey);
     TaskSeries series = (TaskSeries) this.data.get(row);
     Task task = series.get(columnKey.toString());
     if (task != null) {
         result = task.getEnd(); //return the end time of task
     }
     return result;
 }
public Number getStartValue(Comparable rowKey, Comparable columnKey, 
                                 int subinterval) {
     Number result = null;
     int row = getRowIndex(rowKey);
     TaskSeries series = (TaskSeries) this.data.get(row);
     Task task = series.get(columnKey.toString());
     if (task != null) {
         Task sub = task.getSubtask(subinterval);
         if (sub != null) {
             result = sub.getStart();
         }
     }
     return result;
 }
public Number getEndValue(Comparable rowKey, Comparable columnKey, 
                               int subinterval) {
     Number result = null;
     int row = getRowIndex(rowKey);
     TaskSeries series = (TaskSeries) this.data.get(row);
     Task task = series.get(columnKey.toString());
     if (task != null) {
         Task sub = task.getSubtask(subinterval);
         if (sub != null) {
            result = sub.getEnd();
        }
     }
     return result;
 }

and the demo is:

private static IntervalCategoryDataset createDataset()
{
    TaskSeries taskseries = new TaskSeries("Scheduled");
    Task task = new Task("task1", 0, 100);// now task can be added from "double" to "double".
    task.setPercentComplete(1.0D);
    taskseries.add(task);
    Task task1 = new Task("task2", 100, 300);
    taskseries.add(task1);
    Task task2 = new Task("task3",200, 270);
    taskseries.add(task2);

    TaskSeriesCollection taskseriescollection = new TaskSeriesCollection();
    taskseriescollection.add(taskseries);
    return taskseriescollection;
}
private static JFreeChart createChart(IntervalCategoryDataset intervalcategorydataset)
{
    JFreeChart jfreechart = createGanttChart("Schedule Chart Demo", "Task", "Date", intervalcategorydataset, true, true, false);

    CategoryPlot categoryplot = (CategoryPlot)jfreechart.getPlot();
    categoryplot.setRangePannable(true);
    categoryplot.getDomainAxis().setMaximumCategoryLabelWidthRatio(10F);
    CategoryItemRenderer categoryitemrenderer = categoryplot.getRenderer();
    categoryitemrenderer.setSeriesPaint(0, Color.red);
    GanttRenderer ganttrenderer = (GanttRenderer)categoryplot.getRenderer();
    ganttrenderer.setShadowVisible(false);
    ganttrenderer.setBarPainter(new StandardBarPainter() );
    ganttrenderer.setDrawBarOutline(false);
    ganttrenderer.setAutoPopulateSeriesFillPaint(true);
    return jfreechart;
}


 public void createPartControl( Composite parent) {
         JFreeChart chart = createChart(createDataset());

         ChartComposite frame = new ChartComposite(parent, SWT.FILL, chart,
                true);
         frame.pack();
}
Это было полезно?

Решение

The documentation of ChartFactory.createGanttChart(...) is very specific:

Creates a Gantt chart using the supplied attributes plus default values where required. The chart object returned by this method uses a CategoryPlot instance as the plot, with a CategoryAxis for the domain axis, a DateAxis as the range axis, and a GanttRenderer as the renderer.

To solve your problem you would have to "copy" the functionality of this method, but modify it to your requirements (i.e. use different Axis).

You can find the implementation (for example) here in line 1322.

Другие советы

Thank you very much for sharing your solution!

I've created a similar modification for Integer datatypes, which is shorter and cleaner, as you don't need to modify any code in the library.

Here's how it works: I've created a new class TaskNumeric which extends the existing Task, and added a modification to the createGanttChart method, similar to yours. Just add these two classes to your project, and whenever you'd call Task, use TaskNumeric instead. Same counts for ChartFactory and the custom GanttChartFactory.

Here's the Task extension:

public class TaskNumeric extends Task {

    public TaskNumeric(String description, long start, long end) {
        super(description, new Date(start), new Date(end));
    }

    public static TaskNumeric duration(String description, long start, long duration) {
        return new TaskNumeric(description, start, start + duration);
    }

}

And the ChartFactory-mod:

public class GanttChartFactory extends ChartFactory {

    protected static ChartTheme currentTheme = new StandardChartTheme("JFree");

    public static JFreeChart createGanttChart(String title,
            String categoryAxisLabel, String valueAxisLabel,
            IntervalCategoryDataset dataset, boolean legend, boolean tooltips,
            boolean urls) {

        CategoryAxis categoryAxis = new CategoryAxis(categoryAxisLabel);
        ValueAxis valueAxis = new NumberAxis(valueAxisLabel);

        CategoryItemRenderer renderer = new GanttRenderer();
        if (tooltips) {
            renderer.setBaseToolTipGenerator(
                    new IntervalCategoryToolTipGenerator(
                    "{1}: {3} - {4}", NumberFormat.getNumberInstance()));
        }
        if (urls) {
            renderer.setBaseItemURLGenerator(
                    new StandardCategoryURLGenerator());
        }

        CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis,
                renderer);
        plot.setOrientation(PlotOrientation.HORIZONTAL);
        JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,
                plot, legend);
        currentTheme.apply(chart);
        return chart;
    }
}

Demo:

public class GanttDemo extends ApplicationFrame {

    public GanttDemo(String s) {
        super(s);
        JPanel jpanel = createDemoPanel();
        jpanel.setPreferredSize(new Dimension(500, 270));
        setContentPane(jpanel);
    }

    private static JFreeChart createChart(IntervalCategoryDataset dataset) {
        final JFreeChart chart = GanttChartFactory.createGanttChart(
            "Gantt Chart Demo", "Task", "Value", dataset, true, true, false);
        return chart;
    }

    private static IntervalCategoryDataset createDataset() {
        TaskSeries taskseries = new TaskSeries("Scheduled");

        Task task = new TaskNumeric("task1", 0, 5);
        task.setPercentComplete(1.0D);
        taskseries.add(task);
        Task task1 = new TaskNumeric("task2", 2,9);
        taskseries.add(task1);
        Task task2 = TaskNumeric.duration("task3", 6, 5);
        taskseries.add(task2);

        TaskSeriesCollection taskseriescollection = new TaskSeriesCollection();
        taskseriescollection.add(taskseries);
        return taskseriescollection;
    }

    public static JPanel createDemoPanel() {
        JFreeChart jfreechart = createChart(createDataset());
        ChartPanel chartpanel = new ChartPanel(jfreechart);
        chartpanel.setMouseWheelEnabled(true);
        return chartpanel;
    }

    public static void main(String args[]) {
        GanttDemo ganttdemo = new GanttDemo("gantt demo");
        ganttdemo.pack();
        RefineryUtilities.centerFrameOnScreen(ganttdemo);
        ganttdemo.setVisible(true);
    }

}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top