如何在OptaPlanner的用户界面中调整颜色?

问题描述 投票:0回答:1

我目前正在使用OptaPlanner的工作计划算法来创建特定计划。我希望计划中使用的每个执行模式都以不同的颜色显示(而不是所有不同的项目以不同的颜色显示)。是否可以实现这一目标,如果可以,如何实现?我已经在代码中搜索了一段时间,并且不知道如何执行此操作。

jfreechart optaplanner
1个回答
1
投票

使用OptaPlanner项目的一部分的Project Scheduling Swing应用程序很难做到这一点。它使用JFreeChart绘制数据,我找不到将元数据(例如颜色)与正在绘制的数据相关联的简单方法。

您可以重写YIntervalRenderer行为以根据数据项的行(seriesIndex)和列(系列中项目的索引)返回选择的颜色,但是您必须自己保留执行模式和[row, column]之间的映射,这很麻烦。

这里是经过修改的ProjectJobSchedulingPanel的示例,执行上述操作:

public class ProjectJobSchedulingPanel extends SolutionPanel<Schedule> {

    private static final Logger logger = LoggerFactory.getLogger(ProjectJobSchedulingPanel.class);
    private static final Paint[] PAINT_SEQUENCE = DefaultDrawingSupplier.DEFAULT_PAINT_SEQUENCE;

    public static final String LOGO_PATH = "/org/optaplanner/examples/projectjobscheduling/swingui/projectJobSchedulingLogo.png";

    public ProjectJobSchedulingPanel() {
        setLayout(new BorderLayout());
    }

    @Override
    public void resetPanel(Schedule schedule) {
        removeAll();
        ChartPanel chartPanel = new ChartPanel(createChart(schedule));
        add(chartPanel, BorderLayout.CENTER);
    }

    private JFreeChart createChart(Schedule schedule) {
        YIntervalSeriesCollection seriesCollection = new YIntervalSeriesCollection();
        Map<Project, YIntervalSeries> projectSeriesMap = new LinkedHashMap<>(
                schedule.getProjectList().size());
        ExecutionMode[][] executionModeByRowAndColumn = new ExecutionMode[schedule.getProjectList().size()][schedule.getAllocationList().size()];
        YIntervalRenderer renderer = new YIntervalRenderer() {
            @Override
            public Paint getItemPaint(int row, int column) {
                ExecutionMode executionMode = executionModeByRowAndColumn[row][column];
                logger.info("getItemPaint: ExecutionMode [{},{}]: {}", row, column, executionMode);
                return executionMode == null
                        ? TangoColorFactory.ALUMINIUM_5
                        : PAINT_SEQUENCE[(int) (executionMode.getId() % PAINT_SEQUENCE.length)];
            }
        };
        Map<Project, Integer> seriesIndexByProject = new HashMap<>();
        int maximumEndDate = 0;
        int seriesIndex = 0;
        for (Project project : schedule.getProjectList()) {
            YIntervalSeries projectSeries = new YIntervalSeries(project.getLabel());
            seriesCollection.addSeries(projectSeries);
            projectSeriesMap.put(project, projectSeries);
            renderer.setSeriesShape(seriesIndex, new Rectangle());
            renderer.setSeriesStroke(seriesIndex, new BasicStroke(3.0f));
            seriesIndexByProject.put(project, seriesIndex);
            seriesIndex++;
        }
        for (Allocation allocation : schedule.getAllocationList()) {
            int startDate = allocation.getStartDate();
            int endDate = allocation.getEndDate();
            YIntervalSeries projectSeries = projectSeriesMap.get(allocation.getProject());
            int column = projectSeries.getItemCount();
            executionModeByRowAndColumn[seriesIndexByProject.get(allocation.getProject())][column] = allocation.getExecutionMode();
            logger.info("ExecutionMode [{},{}] = {}", seriesIndexByProject.get(allocation.getProject()), column, allocation.getExecutionMode());
            projectSeries.add(allocation.getId(), (startDate + endDate) / 2.0,
                    startDate, endDate);
            maximumEndDate = Math.max(maximumEndDate, endDate);
        }
        NumberAxis domainAxis = new NumberAxis("Job");
        domainAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        domainAxis.setRange(-0.5, schedule.getAllocationList().size() - 0.5);
        domainAxis.setInverted(true);
        NumberAxis rangeAxis = new NumberAxis("Day (start to end date)");
        rangeAxis.setRange(-0.5, maximumEndDate + 0.5);
        XYPlot plot = new XYPlot(seriesCollection, domainAxis, rangeAxis, renderer);
        plot.setOrientation(PlotOrientation.HORIZONTAL);
        // Uncomment this to use Tango color sequence instead of JFreeChart default sequence.
        // This results in color per project mode.
//        DefaultDrawingSupplier drawingSupplier = new DefaultDrawingSupplier(
//                TangoColorFactory.SEQUENCE_1,
//                DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE,
//                DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,
//                DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,
//                DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
//                DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE);
//        plot.setDrawingSupplier(drawingSupplier);
        return new JFreeChart("Project Job Scheduling", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
    }
}

结果:enter image description here

[另一种方法是实现JFreeChart接口并定制DatasetRenderer,以便您可以直接绘制Allocations。类似于JFreeChart中的Gantt chart实现。

或从头开始编写自定义UI。取决于op您愿意付出多少努力:)

© www.soinside.com 2019 - 2024. All rights reserved.