JFreeChart:缩放图表时添加并同步滚动条(Eclipse 插件/SWT)

发布于 2024-12-19 07:04:21 字数 802 浏览 1 评论 0原文

我正在使用 JFreeChart 库在 Eclipse 视图中绘制某些内容,目前我的视图初始化代码如下所示:

@Override
public void createPartControl(Composite parent)
{
    JFreeChart chart = null;

    // Created via different object     
    chart = graph.createLineChart("Test Graph", "x", "y");

    ChartComposite frame = new ChartComposite(parent, SWT.NONE, chart, true);
    frame.setRangeZoomable(false);      
    parent.layout(true);
}

我想在用户放大时向我的图表添加滚动,但到目前为止我找到的所有示例(在演示中)包,此处,以及其他来源)基于 Swing 处理 JPanes 和图表面板。

如何在我的视图的 createPartControl() 函数中实现相同的效果,其中我只有一个 Composite。是否可以仅在 SWT 中执行此操作,或者我应该将 SWT 与 SWING 或 AWT 混合(需要弄清楚如何)?

谢谢

I am using JFreeChart library to plot something in an Eclipse view and currently my code for view initialization looks as follows:

@Override
public void createPartControl(Composite parent)
{
    JFreeChart chart = null;

    // Created via different object     
    chart = graph.createLineChart("Test Graph", "x", "y");

    ChartComposite frame = new ChartComposite(parent, SWT.NONE, chart, true);
    frame.setRangeZoomable(false);      
    parent.layout(true);
}

I wanted to add scrolling to my graph when the user zooms in, but so far all the examples that I found (in the demo package, here, and other sources) are based on Swing dealing with JPanes and ChartPanels.

How can I achieve the same in the createPartControl() function of my view where I have only a Composite. Is it possible to do it in SWT only or should I mix (need to figure out how) SWT with SWING or AWT?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橪书 2024-12-26 07:04:21

除了已接受的答案之外,我还想自己发布一个答案,因为我遇到了一些有关 SlidingXYDataset 的问题:

  1. 该实现允许指定数据集中的点数可以在任何给定时间显示,并且对于大多数用例来说都可以。但在数据集中数据点稀疏非常均匀的情况下,滑动数据将导致域轴改变其范围。
    例如,如果窗口大小为 5 个数据点,前 5 个数据点为 2 个单位,接下来的 5 个数据点为 20 个单位,则滑动时 X 轴可见范围大小将发生变化。
    因此,您可以看到当所有点都绘制在任意位置时,行为会是什么样子。
    这可能是也可能不是期望的行为。在我的例子中,我需要有一个固定的 X 轴可见范围(例如 200 个单位)并始终保持这种范围。

  2. 由于某种原因,我无法通过给它一个空的XYSeriesCollection/TimeSeriesCollection来创建SlidingXYDataset。我需要从一个空数据集开始并实时更新它,并且我必须首先添加无用的数据。但这可能是因为我做错了什么。

话虽如此,可能有解决方法,但我以与接受的答案不同的方式实现了缩放和滚动条。

此示例还展示了当用户在图表上执行缩放操作时如何同步滑块。

首先:您需要创建一个XYLineChart并设置所需的范围(该示例仅针对X轴进行阐述,但也可以应用于Y轴

XYSeries 数据集 = new XYSeries("我的数据集");
XYSeriesCollection datasetCollection = new XYSeriesCollection(数据集);
JFreeChart 图表 = ChartFactory.createXYLineChart("标题", 
                   “x 标签”, 
                   “y 标签”, 
                   数据集集合, 
                   绘图方向.VERTICAL, 
                   真,假,假);

XYPlot 图=图表.getXYPlot();
ValueAxis 域轴=plot.getDomainAxis();
ValueAxis rangeAxis =plot.getRangeAxis();

域Axis.setAutoRange(false);
域Axis.setFixedAutoRange(300); // X 轴上随时可见 300 个单位
域Axis.setLowerBound(0); //从0开始

其次:您需要将图表和滚动条放在父布局内​​。在 SWT 中,您可以通过 FormLayout 的用户来执行此操作

// 鉴于composite是父Composite
FormLayout 布局 = new FormLayout();
复合材料.setLayout(布局);

ChartComposite = new ChartComposite(composite, SWT.NONE, 图表, true);
滑块滑块 = new Slider(composite, SWT.NONE);
sldier.setValues(/* 取决于您的需求 */);

// 将滑块添加到表单底部
FormData sliderLayoutData = new FormData();
sliderLayoutData.left = new FormAttachment(0,0);
sliderLayoutData.bottom = new FormAttachment(100,0);
sliderLayoutData.right = new FormAttachment(100,0);
slider.setLayoutData(sliderLayoutData);

// 现在将 graphComposite 添加到滑块上方的表单中
FormData graphLayoutData = new FormData();
graphLayoutData.left = new FormAttachment(0,0);
graphLayoutData.right = new FormAttachment(100,0);
graphLayoutData.top = new FormAttachment(0,0);
graphLayoutData.bottom = new FormAttachment(slider);      
ChartComposite.setLayoutData(graphLayoutData);    

// 刷新布局
复合布局(真);

现在,每次移动滑块时,您都需要捕获该事件并根据滑块数据使用 to 方法更改图表的域范围:

domainAxis.setLowerBound(最小可见);
  domainAxis.setUpperBound(最大可见);

第三:最后,您需要通过扩展该对象或在创建新对象时覆盖 ChartComposite 的缩放方法

<前><代码>@Override
public void Zoom(矩形选择)
{
XYPlot 绘图 = (XYPlot) getChart().getPlot();
矩形 2D 绘图区域 = 新 矩形 2D.Double( getScreenDataArea().x,
getScreenDataArea().y,
getScreenDataArea().width,
getScreenDataArea().height);

浮点数x1 = (浮点数)plot.getDomainAxis()。
java2DToValue(选择.x,
绘图区域,
绘图.getDomainAxisEdge());

浮点 x2 = (浮点)plot.getDomainAxis()。
java2DToValue(选择.x + 选择.宽度,
绘图区域,
绘图.getDomainAxisEdge());

// x1 和 x2 会将点转换为图表坐标
// 用户为缩放 X 轴所做的选择
// 您可以调整图表以仅显示选定的(缩放)
// 信息本身
域Axis.setLowerBound(x1);
域Axis.setUpperBound(x2);

// 现在调整滑块信息
// 同步到图表的当前视图
sldier.setValues(/* 取决于您的需求 */);
}

希望这个实现可以在其他人的用例中找到它的用途。

In addition to the accepted answer I'd like to post an answer myself, because I ran into a couple of issues regarding to SlidingXYDataset:

  1. The implementation allows to specify the number of points in the dataset that can be shown at any given time and that is OK for most use cases. But in the case where the data points are sparsed very uniformly in the dataset sliding thorugh data will cause the domain axis to change its range.
    For example if the window size is 5 datapoints and first 5 are 2 units appart and the next 5 are 20 units appart the X axis visible range size will change when your are sliding.
    So you can see what the behaviour will look like when all the points are ploted at arbitrary locations.
    This may or may not be a desired behaviour. In my case I needed to have a fixed visible range of the X axis (for example 200 units) and to keep it as such all the time.

  2. For some reason I was not able to create a SlidingXYDataset by giving it an empty XYSeriesCollection/TimeSeriesCollection. I needed to start with an empty dataset and update it in real time and I had to add useless data to start with. But that's maybe because I was doing something wrong.

Having said that above, there might be workarounds for it, but I went and implemented the zooming and scrollbar in a different than the accepted answer's way.

Also this example shows how to sync the slider when user performs a zoom action on the graph.

First: you need to create an XYLineChart and set the desired range (The example is elaborated for X axis only, but can be applied for Y axis as well)

XYSeries dataset = new XYSeries("my dataset");
XYSeriesCollection datasetCollection = new XYSeriesCollection(dataset);
JFreeChart chart = ChartFactory.createXYLineChart("title", 
                   "x label", 
                   "y label", 
                   datasetCollection, 
                   PlotOrientation.VERTICAL, 
                   true, false, false);

XYPlot plot = chart.getXYPlot();
ValueAxis domainAxis = plot.getDomainAxis();
ValueAxis rangeAxis  = plot.getRangeAxis();

domainAxis.setAutoRange(false);
domainAxis.setFixedAutoRange(300); // 300 units visible at anytime on X axis
domainAxis.setLowerBound(0); // start from 0

Second: you need to put both the chart and a scroll bar inside the parent layout. In SWT you can do this for example through the user of FormLayout

// Given that composite is the parent Composite
FormLayout layout = new FormLayout();
composite.setLayout(layout);

chartComposite = new ChartComposite(composite, SWT.NONE, chart, true);
Slider slider = new Slider(composite, SWT.NONE);
sldier.setValues(/* depends on your needs */);

// add the slider to the bottom of the form
FormData sliderLayoutData = new FormData();
sliderLayoutData.left = new FormAttachment(0,0);
sliderLayoutData.bottom = new FormAttachment(100,0);
sliderLayoutData.right = new FormAttachment(100,0);
slider.setLayoutData(sliderLayoutData);

// now add the graphComposite to the form above the slider
FormData graphLayoutData = new FormData();
graphLayoutData.left = new FormAttachment(0,0);
graphLayoutData.right = new FormAttachment(100,0);
graphLayoutData.top = new FormAttachment(0,0);
graphLayoutData.bottom = new FormAttachment(slider);      
chartComposite.setLayoutData(graphLayoutData);    

// refresh the layout
composite.layout(true);

Now every time you move the slider, you need to capture that event and change the chart's domain range with the to methods according to you slider data:

  domainAxis.setLowerBound(minimum visible);
  domainAxis.setUpperBound(maximum visible);

Third: Finaly you need to override the zoom method of the ChartComposite either by extending this object or right above when you create a new one

@Override 
public void zoom(Rectangle selection)
{
  XYPlot plot = (XYPlot) getChart().getPlot();
  Rectangle2D plotArea = new Rectangle2D.Double( getScreenDataArea().x,
          getScreenDataArea().y,
          getScreenDataArea().width,
          getScreenDataArea().height);

  float x1 = (float) plot.getDomainAxis().
                       java2DToValue(selection.x, 
                                     plotArea, 
                                     plot.getDomainAxisEdge());

  float x2 = (float) plot.getDomainAxis().
                       java2DToValue(selection.x + selection.width, 
                                     plotArea, 
                                     plot.getDomainAxisEdge());

  // x1 and x2 will have the points transalted into chart coordinates
    // of the selection the user made for zooming the X axis  
  // you can adjust your chart to show only the selected (zoomed) 
    // information as such
  domainAxis.setLowerBound(x1);
  domainAxis.setUpperBound(x2);

  // and now adjust the slider information so it's 
    // synced to your graph's current view
  sldier.setValues(/* depends on your needs */);
}

Hope this implementation can find it's use in other people's use cases.

小女人ら 2024-12-26 07:04:21

您可以查看 SlidingXYDataset,提到此处,或此处显示的分页方法

You might look at SlidingXYDataset, mentioned here, or the paging approach shown here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文