JFreeChart MouseListener无法解析图表元素 [英] JFreeChart MouseListener doesn't resolve chart elements

查看:47
本文介绍了JFreeChart MouseListener无法解析图表元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有堆叠的条形图,我希望能够在其中选择堆叠中的各个条形.但是ChartMouseListener不会将ChartMouseEvent解析为相应的ChartEntity.这是听众的片段:

I've got stacked bar chart where I want to be able to select individual bars in the stack. But ChartMouseListener doesn't resolve ChartMouseEvent into corresponding ChartEntity. Here's the listener snippet :

    public void chartMouseClicked(ChartMouseEvent event){
        ChartEntity entity = event.getEntity();
        if(entity != null && (entity instanceof XYItemEntity) ){
            XYItemEntity item = (XYItemEntity)entity;
            renderer.select(item.getSeriesIndex(), item.getItem());
            return;
        }

        // deselect
        renderer.select(-1,-1);
    }

问题是当我显然单击某些栏时event.getEntity()返回null.请注意,并非所有障碍都失败了.我越靠近图表的右端,坐标移位就越明显.下面的快照显示了在所选栏外单击时实际显示的所选栏.我在SWT复合中使用JFreeChart.谁能确认这是错误的行为,还是有解决方法?

The problem is that event.getEntity() returns null when I am obviously clicking on some of the bars. Note that NOT all the bars fail. The further I go to the right end of the chart, the more obvious is the shift in coordinates. Snap shot below showing that selected bar actually appears when clicking outside of it. I am using JFreeChart within SWT composite. Can anyone confirm that this is a buggy behavior or is there a workaround?

下面是完整的 sscce ,在您运行它并单击栏后-它会显示小指.然后重新调整窗口大小并尝试选择栏-它会丢失.而且我认为错过的原因是新尺寸的作用.

Below is complete sscce, after you run it and click on bars - it will show up pinky. Then re-size the window and try to select bars - it will miss. And I think the miss is the function of the new size.

import java.awt.Color;
import java.awt.Paint;
import java.util.Random;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.event.RendererChangeEvent;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYBarRenderer;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.data.time.Day;
import org.jfree.data.time.Hour;
import org.jfree.data.time.TimeTableXYDataset;
import org.jfree.data.xy.TableXYDataset;
import org.jfree.experimental.chart.swt.ChartComposite;

public class StackedChartSwt {
    private StackedRenderer renderer;
    private Color[] colors = new Color[]{
            new Color(230,240,255), 
            new Color(240,255,240), 
            new Color(255,255,255), 
            new Color(255,255,240), 
            new Color(255,240,240), 
            new Color(240,240,240)
    };

    public StackedChartSwt(){
        Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());

        JFreeChart chart = createStackedChart(createStackedDataset());
        ChartComposite chartComposite = new ChartComposite(shell, SWT.NONE, chart, false, false, false, false, false);
        chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
        chartComposite.setRangeZoomable(false);
        chartComposite.setMenu(null);
        chartComposite.addChartMouseListener(new ThisMouseListener());
        shell.setSize(800, 600);
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
              display.sleep();
            }
          }

          display.dispose();        
    }

    private JFreeChart createStackedChart(TableXYDataset tablexydataset) {
        DateAxis dateaxis = new DateAxis();
        dateaxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
        NumberAxis numberaxis = new NumberAxis("Event counts");
        renderer = new StackedRenderer();
        XYPlot plot = new XYPlot(tablexydataset, dateaxis, numberaxis, renderer);
        plot.setBackgroundPaint(Color.white);
        plot.setDomainGridlinePaint(Color.lightGray);
        plot.setDomainGridlinesVisible(true);
        plot.setRangeGridlinesVisible(true);
        plot.setRangeGridlinePaint(Color.lightGray);

        JFreeChart chart = new JFreeChart(null, plot);
        chart.setBackgroundPaint(Color.white);
        chart.setBorderVisible(false);
        chart.setBorderPaint(null);

        return chart;
    }

    class StackedRenderer extends StackedXYBarRenderer{
        int selectedRow=-1, selectedCol=-1;
        public StackedRenderer(){
            setDrawBarOutline(true);
            setBarPainter(new StandardXYBarPainter());
            setShadowVisible(false);
            setSeriesPaint(0, Color.blue);
            setMargin(0.2);
        }

        public void select(int row, int col){
            selectedRow = row;
            selectedCol = col;
            notifyListeners(new RendererChangeEvent(this));
        }

        @Override
        public Paint getItemPaint(final int row, final int col){
            if(row == selectedRow && col == selectedCol)
                return Color.pink;
            return colors[row];
        }
    } 

    class ThisMouseListener implements ChartMouseListener{
        public void chartMouseMoved(ChartMouseEvent event){
        }

        public void chartMouseClicked(ChartMouseEvent event){
            ChartEntity entity = event.getEntity();
            if(entity != null && (entity instanceof XYItemEntity) ){
                XYItemEntity item = (XYItemEntity)entity;
                renderer.select(item.getSeriesIndex(), item.getItem());
                return;
            }

            // deselect
            renderer.select(-1,-1);
        }
    }

    private TableXYDataset createStackedDataset(){
        Random random = new Random(0);
        TimeTableXYDataset ds = new TimeTableXYDataset();
        Day day = new Day();
        for( int i = 0; i < 24; i++ ){
            Hour hour = new Hour( i, day );
            ds.add(hour, random.nextInt( 20 ), "A");
            ds.add(hour, random.nextInt( 20 ), "B");
            ds.add(hour, random.nextInt( 20 ), "C");
            ds.add(hour, random.nextInt( 20 ), "D");
            ds.add(hour, random.nextInt( 20 ), "E");
            ds.add(hour, random.nextInt( 20 ), "F");
        }

        return ds;
    }

    public static void main(String[] args){
        new StackedChartSwt();
    }
}

推荐答案

好的,我发现了问题.在SWT中,有多个构造函数可创建ChartComposite,大多数使用默认值来指定最小/最大宽度和高度.就我而言,只要将图表放大到DEFAULT_MAXIMUM_DRAW_WIDTH(800px)以上,坐标就会变得混乱.因此,解决方案是使用完整的构造函数并为您的显示指定相关边界.很难破解...主要是由于缺乏适当的文档.

OK, I've found the problem. In SWT there are several constructors to create ChartComposite, most of the use defaults which specify min/max width and height. In my case, whenever I've enlarged the chart above DEFAULT_MAXIMUM_DRAW_WIDTH (800px) - the coordinates start to get messy. So, the solution is to use full constructor and specify relevant boundaries for your display. It was a tough one to crack... mainly due to lack of proper documentation.

这篇关于JFreeChart MouseListener无法解析图表元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆