2015-07-02 23 views

回答

2

显然不可能用当前的JFreeChart API修改修改键,如讨论here(但它在管道中)。

然而,一切都在那里以编程方式平移图表,所以你可以尝试以下方法:

  • 添加MouseMotionListenerChartPanel跟踪mouseDragged()事件。
  • 从这些事件中,计算所需的图表移动。
  • 直接致电XYPlot.panDomainAxes()XYPlot.panRangeAxis()(API here)。从ChartPanelsource code

的灵感:

/** 
* 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()); 
    } 

    ... 

} 

编辑:我注意到当前API的唯一问题是,panMask是私人的,你为什么不尝试破解与反思领域:

Field mask = ChartPanel.class.getDeclaredField("panMask"); 
mask.setAccessible(true); 
mask.set(yourChartPanel, Integer.valueOf(0)); // The "0" mask is equivalent to no mask. You could also set a different modifier. 
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); 
    } 
    }; 
+0

在回答堆栈溢出时,最好对你的代码做些什么解释。由于代码唯一的答案对于提出问题的OP来说可能是不可理解的 – SuperBiasedMan

0

解决方案仍不能提供新的版本,所以我放什么完美的作品对我来说,它也自动变焦范围轴滚动时:

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的行为像其他专业制图软件一样。