- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我目前正在尝试弄清楚,jfreechart
拆分为 swing(1.5) 和 JavaFX (1.0.1) 是如何影响 JavaFX 部分的。据我(关于这个主题的知识非常有限)了解 jfree-fx
使用 fxgraphics2d
将其原始 Swing 组件(?)绘制到 FX-canvas 中以添加此进入 JavaFX 节点。
现在我的问题是,fxgraphics2d
对象是否仍然可以与之交互?我的意思是像工具提示和滚动以及类似的正常 jfreechart
提供的东西。由于我的知识和时间有限,我想知道,是否值得深入研究 jfree-fx(如果这些图表仍然可以与之交互),或者这些图表是否只是实际图表的图片而不能与之交互。然后我需要找到更好的解决方案。
我目前正在学习如何在我的 Java 应用程序中构建烛台图表。虽然我设法仅使用 JavaFX 构建了一个图表,但一旦绘制了数百个烛台,它的性能就非常糟糕。
然后我遇到了 jfreechart
,我读到了它的性能远高于内部 JavaFX 图表可能性。所以今天我设法用 jfreechart-fx
构建了我的第一个图表,性能还不错。此外,我发现构建这些图表更加直观......但我不确定 jfree-fx
版本是否仅将图像或真实图表对象打印到节点。 (我在某处读到有关将图表转换为图像以提高绘图性能的内容...)
感谢您提供有关该主题的任何信息。
例如,这里是我的 JFreeChart 类,它已正确绘制,但我无法使用鼠标与图表进行任何交互。例如。我想使用鼠标滚轮放大/缩小,我想通过单击鼠标左键将图表向左/右平移。这就是为什么我担心我现在只看图像的原因。我通过谷歌找到的所有可行解决方案似乎都只针对 JFreeChart
而不是 JFreeChart-FX
。
package org.ezstrats.jfreeChart;
import javafx.collections.ObservableList;
import org.ezstrats.model.chartData.Candlestick;
import org.ezstrats.model.chartData.Chart;
import org.ezstrats.model.chartData.Exchange;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.HighLowItemLabelGenerator;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.ohlc.OHLCSeries;
import org.jfree.data.time.ohlc.OHLCSeriesCollection;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
public class JFreeCandlestickChart extends JPanel {
private static final DateFormat READABLE_TIME_FORMAT = new SimpleDateFormat("kk:mm:ss");
private OHLCSeries ohlcSeries;
private TimeSeries volumeSeries;
private JFreeChart candlestickChart;
public JFreeCandlestickChart(String title) {
ObservableList<Candlestick> candlesticks = Exchange.getCandlesticks();
// Create new chart
candlestickChart = createChart(title, candlesticks);
// Create new chart panel
final ChartPanel chartPanel = new ChartPanel(candlestickChart);
chartPanel.setPreferredSize(new Dimension(832, 468));
chartPanel.getChart().getXYPlot().getDomainAxis().setAutoRange(false);
chartPanel.getChart().getXYPlot().getDomainAxis().setLowerBound(candlesticks.get(candlesticks.size() - 300).getTimestampOpen());
chartPanel.getChart().getXYPlot().getDomainAxis().setUpperBound(candlesticks.get(candlesticks.size() - 1).getTimestampOpen());
// Enable zooming - not workign?! ...
chartPanel.setMouseZoomable(true);
chartPanel.setMouseWheelEnabled(true);
chartPanel.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
// process before
super.mouseDragged(e);
chartPanel.getChart().getXYPlot().getDomainAxis().configure();
// process after
}
});
add(chartPanel, BorderLayout.CENTER);
}
public JFreeChart createChart(String title, ObservableList<Candlestick> candlesticks){
/**
* 1st:
* Creating candlestick subplot
*/
// Create OHLCSeriesCollection as a price dataset for candlestick chart
OHLCSeriesCollection candlestickDataset = new OHLCSeriesCollection();
ohlcSeries = new OHLCSeries("Price");
candlestickDataset.addSeries(ohlcSeries);
// Create candlestick chart priceAxis
NumberAxis priceAxis = new NumberAxis("Price");
priceAxis.setAutoRangeIncludesZero(false);
// Create candlestick chart renderer
CandlestickRenderer candlestickRenderer = new CandlestickRenderer(CandlestickRenderer.WIDTHMETHOD_AVERAGE,
false,
new HighLowItemLabelGenerator(new SimpleDateFormat("kk:mm"), new DecimalFormat("0.00000000")));
// Create candlestickSubplot
XYPlot candlestickSubplot = new XYPlot(candlestickDataset, null, priceAxis, candlestickRenderer);
candlestickSubplot.setBackgroundPaint(Color.white);
/**
* 2nd:
* Creating volume subplot
*/
// creates TimeSeriesCollection as a volume dataset for volume chart
TimeSeriesCollection volumeDataset = new TimeSeriesCollection();
volumeSeries = new TimeSeries("Volume");
volumeDataset.addSeries(volumeSeries);
// Create volume chart volumeAxis
NumberAxis volumeAxis = new NumberAxis("Volume");
volumeAxis.setAutoRangeIncludesZero(true);
// Set to no decimal
volumeAxis.setNumberFormatOverride(new DecimalFormat("0"));
// Create volume chart renderer
XYBarRenderer timeRenderer = new XYBarRenderer();
timeRenderer.setShadowVisible(false);
timeRenderer.setDefaultToolTipGenerator(new StandardXYToolTipGenerator("Volume--> Time={1} Size={2}",
new SimpleDateFormat("kk:mm"), new DecimalFormat("0")));
// Create volumeSubplot
XYPlot volumeSubplot = new XYPlot(volumeDataset, null, volumeAxis, timeRenderer);
volumeSubplot.setBackgroundPaint(Color.white);
/**
* 3rd:
* Adding Candles to this chart
**/
for (Candlestick candle: candlesticks){
addCandleToChart(candle.getTimestampOpen(),
candle.getPriceOpen(),
candle.getPriceHigh(),
candle.getPriceLow(),
candle.getPriceClose(),
candle.getVolumeQuote());
}
/**
* 4th:
* Create chart main plot with two subplots (candlestickSubplot,
* volumeSubplot) and one common dateAxis
*/
// Creating charts common dateAxis
DateAxis dateAxis = new DateAxis("Time");
dateAxis.setDateFormatOverride(new SimpleDateFormat("dd.mm.yy kk:mm"));
//dateAxis.setRange();
// reduce the default left/right margin from 0.05 to 0.02
dateAxis.setLowerMargin(0.02);
dateAxis.setUpperMargin(0.02);
dateAxis.setLabelAngle(0);
// Create mainPlot
CombinedDomainXYPlot mainPlot = new CombinedDomainXYPlot(dateAxis);
mainPlot.setGap(10.0);
mainPlot.add(candlestickSubplot, 4);
mainPlot.add(volumeSubplot, 1);
mainPlot.setOrientation(PlotOrientation.VERTICAL);
mainPlot.setDomainPannable(true);
JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, mainPlot, false);
//chart.removeLegend();
// Einbetten in JScrollPaenl??? um Scrollen zu ermöglichen...
// ChartPanel chartPanel = new ChartPanel(chart);
return chart;
}
/**
* Fill series with data.
*
* @param c opentime
* @param o openprice
* @param h highprice
* @param l lowprice
* @param c closeprice
* @param v volume
*/
private void addCandleToChart(long time, double o, double h, double l, double c, double v) {
// Add bar to the data. Let's repeat the same bar
FixedMillisecond t = new FixedMillisecond(time);
//READABLE_TIME_FORMAT.parse(String.valueOf(time)));
ohlcSeries.add(t, o, h, l, c);
volumeSeries.add(t, v);
}
public void setOhlcSeries(OHLCSeries ohlcSeries) {
this.ohlcSeries = ohlcSeries;
}
public void setVolumeSeries(TimeSeries volumeSeries) {
this.volumeSeries = volumeSeries;
}
public OHLCSeries getOhlcSeries() {
return ohlcSeries;
}
public TimeSeries getVolumeSeries() {
return volumeSeries;
}
public JFreeChart getCandlestickChart() {
return candlestickChart;
}
}
最佳答案
我没有详细研究 jFreeChart,但我认为它与内置 JavaFX 图表 API 之间的主要区别在于 jFreeChart 使用 Canvas 实现其实现,而内置图表使用场景图。粗略地说,虽然不完全是,它类似于 retained mode (scene graph) vs immediate mode (canvas) 的定义。 .
或许可以为 Canvas 渲染的图形添加交互性。除了基本的全图缩放和拖动操作之外,它在技术上可能具有挑战性。在 StackOverflow 答案的上下文中,实现或演示添加此类与 Canvas 渲染图形的交互性超出了我准备做的事情。
JFreeChart 包含一个interaction
包:
我建议您研究交互包,尝试使用它,看看它是否提供您需要的交互级别。
正如 Roger 在评论中提到的那样,通过将图表包装在 ChartViewer 中,您可以在 JFreeChartFX 图表上获得一些基本交互。使用 ChartViewer(JFreeChart myChart)
。
相关问题:
Canvas 与 SceneGraph 的旁白
包含有关 Canvas 如何工作的信息,以便您更好地了解这里发生的事情(请注意,此处的所有内容可能不是 100% 正确,但足够接近以帮助理解)。
从技术上讲,JavaFX 仅使用 SceneGraph 进行渲染。 canvas内部是如何实现的,据我了解,每个canvas都是scenegraph中的一个节点,自带一个绘制指令的命令队列。当您在 Canvas 上绘制时,它不会立即绘制,而是将绘图命令放入队列中,然后在某个时候,在下一个 60fps 绘图脉冲完成之前,它将这些渲染到图像缓冲区,然后中继到JavaFX 节点。一旦执行, Canvas 命令队列就会忘记旧命令,因此所有内容最终都以像素形式结束。您可以跟踪应用程序中的绘图命令,并根据需要重新发出它们以从头开始重新绘制 Canvas ,但 Canvas 对此无济于事。
JFreeChartFX 正在做的是提供一个适配器,使 JavaFX Canvas 看起来像一个 Swing 绘画表面,这样 JFreeChart 的繁重工作和内部引擎就可以用来发出所有的绘图命令,并且可以将这些命令渲染到JavaFX Canvas 或 Swing Canvas ,具体取决于所需的输出 UI 技术。
如果 JFreeChart 还为 JavaFX 事件而不是 Swing 事件提供了类似的适配器,并且如果 JFreeChart 已经有使用 Swing 事件进行交互的方法,那么它可能会使用类似的适配器或 Swing 事件的替换来为 JFreeChartFX 添加交互性机制。也许这就是上面链接的 interaction
包正在做的事情。
关于java - jfreechart-fx 1.0.1 图表是否可以与 fxgraphics2d 构建和呈现的图像进行交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57693217/
我有一个 aspx 应用程序。在每个 GET 中,服务器以包含除表格网格之外的所有内容的“基本”html 进行响应。 这个“网格信息”包含在页面中隐藏的输入类型(json 格式)中。 这是设计使然,无
阅读有关 iOS 中 UIViewControllers 更改的文档,我试图弄清楚呈现模态视图 Controller 之间的交互如何在自定义容器 View Controller 内工作。最终,我希望能
我正忙于编写自己的 JSF2 UIComponent 及其相关的渲染器。我所有的 UIComponent 都实现了 ClientBehaviorHolder。我不明白的是如何真正呈现 ClientBe
我正在开发一个使用UIPopoverController的应用程序,我在呈现该弹出窗口时遇到问题,我有一个添加在self.view上的UIView,并在该 View 上添加了一个表格 View ,该表
我有一个简单的应用程序,我想在用户首次登录应用程序时在其中显示一个 PageViewController。他们查看教程后,在下一次加载时不会显示 PageViewController。 但是我收到了以
我正在尝试制作一个小型的backbone.js 应用程序,但在事情的顺序上很挣扎。 在我的 html 文件中,标题中有两个脚本 block : jQuery(function(){
我有一个以模型为来源的表格: $form->setModel("test"); 在模型中,我们可以定义字段类型,例如:boolean 将在表单中制作复选框。 现在我们如何定义呈现为单选按钮的类型? 最
fabricJS 版本 2.2.3 测试 jsFiddle 我正在尝试使用 LabeledRect 子类,但我的问题是,每当我尝试从 JSON 加载它时,它都不会呈现,并且在控制台中也没有出现错误。请
在我的 Xaml 中,我定义了一个资源作为 vehicleDataInput,它提供一些文本框供用户输入数据。如果我没有为它定义一个 x:Key ,它将在我的应用程序中出现并按其应有的方式工作。问题是
我在 React 中创建了一个 Symbol 组件来轻松呈现 HTML Symbols像 euro 这样的名字将呈现 €(€) 或 sum 呈现 ∑(∑). 问题是,如果我只渲染 HTML 代码,我将
我尝试渲染一个 View ,该 View 工作正常,但似乎无法获得传递给它的模型对象。我不知道原因,因为根据所有手册和示例,这应该非常简单。 模型对象 class Race { def dis
我正在尝试为Grails项目添加一个简单功能,类似于youtube,它将允许用户喜欢/不喜欢文章。有一个非常原始的页面来显示带有喜欢的文章和一个使“喜欢”成为可能的 Controller 。 las,
我的应用程序中的第一个 ViewController 子类 UIImagePickerController 然后通过 didFinishPickingMediaWithInfo 回调,我执行以下操作:
我正在做一个简单的 redux/react todo 应用程序。我无法显示待办事项。我能够 console.log 数据,但无法显示它。我做错了什么? 我把文件分开了,这是我的app.js: impo
我正在尝试呈现一个导航 Controller ,它似乎可以工作并呈现导航 Controller 。但是,即使它有效,我仍然不断收到错误? 我的代码 let vc = storyboard.instan
我正在重新创建一个简单版本的 snapchat 应用程序,但遇到了一个恼人的小问题,我似乎无法找到解决办法。 我查看了一些答案,例如 this one但没有运气。 总体概念与 snapchat 用户单
我在呈现警报时遇到问题。我正在使用 UIAlertController。当用户按下提交按钮时,在应用程序执行某些操作时,需要立即显示“请稍候..”的警报。操作完成后,警报将消失。尽管应该在我开始执行操
我只是想用 Kinetic 渲染图像,但没有出现,也没有出现错误。 可以找到 fiddle here . 源代码: $( function() { var stage = new Kineti
我正在使用 Phantomjs 检查我的应用程序。我正在查看的页面包含很多组件,并且由 Angularjs 提供支持。我的测试服务器很慢。在 onLoadFinished 事件中,我使用渲染对网页进行
我有一个变量,它的字符串包含我所有的文档,如下所示: var string = " ReportHelloWorld"; 我想打开一个正确插入和显示此报告的新页面,但不知道如何操作。我该怎么办? 感谢
我是一名优秀的程序员,十分优秀!