平移图表使用鼠标 - Jfreechart

时间:2015-07-02 19:31:47

标签: java jfreechart

我们可以在JfreeChart中将平移功能实现为鼠标拖动事件吗?现在我按 CTRL 并拖动鼠标来平移图表。我想通过拖动鼠标来实现平移功能。这可能吗?

3 个答案:

答案 0 :(得分:2)

显然不可能使用当前的JFreeChart API更改修饰符键,如here所述(但它正在管道中)。

但是,所有内容都是以编程方式平移图表,因此您可以尝试以下操作:

  • procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); begin if CurUninstallStep = usPostUninstall then begin RemoveDir(ExpandConstant('{userdocs}\Games')) end; end; 添加MouseMotionListener以跟踪ChartPanel个事件。
  • 从这些事件中,计算所请求的图表移动。
  • 直接致电mouseDragged()XYPlot.panDomainAxes()(API here)。

XYPlot.panRangeAxis() source code获取灵感:

ChartPanel

编辑:注意到当前API的唯一问题是/** * Temporary storage for the width and height of the chart * drawing area during panning. */ private double panW, panH; /** The last mouse position during panning. */ private Point panLast; /** * The mask for mouse events to trigger panning. * * @since 1.0.13 */ private int panMask = InputEvent.CTRL_MASK; ... /** * Handles a 'mouse pressed' event. * <P> * This event is the popup trigger on Unix/Linux. For Windows, the popup * trigger is the 'mouse released' event. * * @param e The mouse event. */ @Override public void mousePressed(MouseEvent e) { if (this.chart == null) { return; } Plot plot = this.chart.getPlot(); int mods = e.getModifiers(); if ((mods & this.panMask) == this.panMask) { // can we pan this plot? if (plot instanceof Pannable) { Pannable pannable = (Pannable) plot; if (pannable.isDomainPannable() || pannable.isRangePannable()) { Rectangle2D screenDataArea = getScreenDataArea(e.getX(), e.getY()); if (screenDataArea != null && screenDataArea.contains( e.getPoint())) { this.panW = screenDataArea.getWidth(); this.panH = screenDataArea.getHeight(); this.panLast = e.getPoint(); setCursor(Cursor.getPredefinedCursor( Cursor.MOVE_CURSOR)); } } // the actual panning occurs later in the mouseDragged() // method } } else if (this.zoomRectangle == null) { ... } } ... /** * Handles a 'mouse dragged' event. * * @param e the mouse event. */ @Override public void mouseDragged(MouseEvent e) { // if the popup menu has already been triggered, then ignore dragging... if (this.popup != null && this.popup.isShowing()) { return; } // handle panning if we have a start point if (this.panLast != null) { double dx = e.getX() - this.panLast.getX(); double dy = e.getY() - this.panLast.getY(); if (dx == 0.0 && dy == 0.0) { return; } double wPercent = -dx / this.panW; double hPercent = dy / this.panH; boolean old = this.chart.getPlot().isNotify(); this.chart.getPlot().setNotify(false); Pannable p = (Pannable) this.chart.getPlot(); if (p.getOrientation() == PlotOrientation.VERTICAL) { p.panDomainAxes(wPercent, this.info.getPlotInfo(), this.panLast); p.panRangeAxes(hPercent, this.info.getPlotInfo(), this.panLast); } else { p.panDomainAxes(hPercent, this.info.getPlotInfo(), this.panLast); p.panRangeAxes(wPercent, this.info.getPlotInfo(), this.panLast); } this.panLast = e.getPoint(); this.chart.getPlot().setNotify(old); return; } ... } ... /** * Handles a 'mouse released' event. On Windows, we need to check if this * is a popup trigger, but only if we haven't already been tracking a zoom * rectangle. * * @param e information about the event. */ @Override public void mouseReleased(MouseEvent e) { // if we've been panning, we need to reset now that the mouse is // released... if (this.panLast != null) { this.panLast = null; setCursor(Cursor.getDefaultCursor()); } ... } 是私有的,为什么不尝试使用反射破解该字段:

panMask

答案 1 :(得分:1)

解决方案仍然没有提供新版本,所以我为我提供了完美无缺的工作,它还滚动时自动缩放范围轴:

    ChartPanel panel = new ChartPanel(chart);
    panel.setMouseZoomable(false);
    panel.setMouseWheelEnabled(true);
    panel.setDomainZoomable(true);
    panel.setRangeZoomable(false);
    panel.setPreferredSize(new Dimension(1680, 1100));
    panel.setZoomTriggerDistance(Integer.MAX_VALUE);
    panel.setFillZoomRectangle(false);
    panel.setZoomOutlinePaint(new Color(0f, 0f, 0f, 0f));
    panel.setZoomAroundAnchor(true);
    try {
        Field mask = ChartPanel.class.getDeclaredField("panMask");
        mask.setAccessible(true);
        mask.set(panel, 0);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    panel.addMouseWheelListener(arg0 -> panel.restoreAutoRangeBounds());

现在JFreeChart的行为与任何其他专业图表软件一样。

答案 2 :(得分:0)

这是我的解决方案。

此致 TA

 ChartPanel cp = new ChartPanel(chart)
  {
     /**
      * A hack to change the zoom and panning function.
      * With this override we can pan around by dragging.
      * If SHIFT is pressed we get the zoom rectangle.
      * @param e
      */
     @Override
     public void mousePressed(MouseEvent e)
     {
        int mods = e.getModifiers();

        int panMask = MouseEvent.BUTTON1_MASK;

        if (mods == MouseEvent.BUTTON1_MASK+MouseEvent.SHIFT_MASK)
        {
           panMask = 255; //The pan test will match nothing and the zoom rectangle will be activated.
        }

        try
        {
           Field mask = ChartPanel.class.getDeclaredField("panMask");
           mask.setAccessible(true);
           mask.set(this, panMask);

        }
        catch (Exception ex)
        {
           ex.printStackTrace();
        }

        super.mousePressed(e);
     }
  };