如何正确地将 MouseHandler 添加到我的 JFreeChart-FX 以从左向右拖动图表

2023-12-01

我设法使用创建了烛台图JFreeChart-FX并使用显示它fxgraphics2dAPI。但我对如何与我的图表进行任何交互感到非常困惑,并且需要一些帮助。

如果您在正确的方向上提供任何帮助,我将非常感激。

我开始于this例如,获取我的初始图表并对其进行更改,以便它使用我的数据。然后我用一个自定义的Canvas,它利用fxgraphics2d使JPanel组件可作为我的节点访问JavaFX应用。 所以我知道有一个特定的例子PanHandlerFX class,但我无法利用它。据我能够研究(例如here),我需要添加PanHandlerFX类到列表availableMouseHandlers我的 ChartCanvas 的。但我的canvas不提供类似的东西availableMouseHandlers。我现在感到迷失了,因为关于 JFree-FX 图表的教程和信息太少了,而且文档也对我没有帮助。

这是我的自定义画布类:

import javafx.scene.canvas.Canvas;
import org.jfree.chart.JFreeChart;
import org.jfree.fx.FXGraphics2D;

import java.awt.geom.Rectangle2D;

public class ChartCanvas extends Canvas {

    JFreeChart chart;
    private FXGraphics2D graphics2D;

    public ChartCanvas(JFreeChart chart) {
        this.chart = chart;
        this.graphics2D = new FXGraphics2D(getGraphicsContext2D());
        // Redraw canvas when size changes.
        widthProperty().addListener(e -> draw());
        heightProperty().addListener(e -> draw());

    }

    private void draw() {
        double width = getWidth();
        double height = getHeight();
        getGraphicsContext2D().clearRect(0, 0, width, height);
        this.chart.draw(this.graphics2D, new Rectangle2D.Double(0, 0, width, height));
        //(this.graphics2D,, new Rectangle2D.Double(0, 0, width, height));
    }
}

这是我的自定义 JFreeChart:

import javafx.collections.ObservableList;
import org.ezstrats.model.chartData.Candlestick;
import org.ezstrats.model.chartData.Exchange;
import org.jfree.chart.ChartPanel;
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.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;
    }
}

这就是我打印图表(main.class)的方式:

    // Switching Views
    public void drawNewChart(JFreeChart newChart){
        centerChart.getChildren().removeAll();

        ChartCanvas chartCanvas = new ChartCanvas(newChart);

        centerChart.getChildren().add(chartCanvas);
        chartCanvas.widthProperty().bind(centerChart.widthProperty());
        chartCanvas.heightProperty().bind(centerChart.heightProperty());

    }

如图所示here,构建一个ChartViewer和你的JFreeChart创建交互式图表。观看者被封闭ChartCanvas将管理PanHandlerFX为你。作为一个具体示例,将以下行添加到example,然后按照描述拖动here:

plot.setDomainPannable(true);

原来的:

original

向右拖动后:

drag right

顺便说一句,您可能会发现JavaFX 演示在这方面很有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何正确地将 MouseHandler 添加到我的 JFreeChart-FX 以从左向右拖动图表 的相关文章

  • JNA - EnumProcessModules() 未返回所有 DLL?

    我试图从游戏中读取坐标 当我在通过 OpenProcess 接收的 HANDLE 上使用 ReadProcessMemory 以及我在 CheatEngine 中找到的内存时 效果非常好 例如 如果我知道正在运行的进程中的浮点值是0x5AB
  • Java 字符串哈希码缓存

    字符串不变性的优点之一是哈希码缓存以实现更快的访问 在这种情况下 如何处理具有相同哈希码的字符串的缓存 在这种情况下它真的能提高性能吗 在这种情况下 如何处理具有相同哈希码的字符串的缓存 被缓存的是字符串的哈希码 它被缓存在私有的int字符
  • H.323,如何制作一个没有媒体的简单环。该脚本遵循 Q.931 设置,但仍然无法正常工作

    谁能帮我解决这个问题吗 当我发送此请求时 我在wireshark中看到数据包将发送到1720 tcp端口中的SJPhone 但 SJPhone 仍然没有响铃 我想让它响起 无论媒体 我非常感谢您的支持 我一定缺少消息协议细节来实现这个 请给
  • 通过 html tidy 提供渲染 jsp 页面

    我有一个在 Glassfish 上运行的 Java 项目 它会呈现一些难看的 HTML 这是使用各种内部和外部 JSP 库的副作用 我想设置某种渲染后过滤器 通过 HTMLTidy 提供最终的 HTML 这样源代码就很好且整洁 有助于调试
  • 使用正则表达式验证输入字符串是否为 0-255 之间的数字

    我在将输入字符串与正则表达式匹配时遇到问题 我想验证输入数字在 0 255 之间并且长度最多应为 3 个字符 代码工作正常 但当我输入 000000 至任意长度时 显示 true 而不是 false 这是我的代码 String IP 000
  • ResultSet:通过索引检索列值与通过标签检索

    使用 JDBC 时 我经常遇到这样的结构 ResultSet rs ps executeQuery while rs next int id rs getInt 1 Some other actions 我问自己 以及代码作者 为什么不使用
  • 初始堆大小无效。无法创建Java虚拟机

    我遇到了下一个问题 我尝试通过startup bat手动启动Tomcat 但似乎没有显示任何结果 然后我尝试运行shutdown bat 控制台显示如下 D apache tomcat 7 0 35 bin gt startup bat U
  • 从字符串生成密钥?

    我需要从字符串生成一个密钥 以便我始终可以从同一字符串创建相同的密钥 具体来说是一个Key对象 这样我就可以用它来创建Cipher进而创建SealedObject 这在 Java 中可行吗 我应该考虑什么类 方法组合才能做到这一点 对于 A
  • AffineTransform.rotate() - 如何同时缩放、旋转和缩放?

    我有以下代码 它可以完成我想要绘制一个上面有一些棋子的棋盘的 第一部分 Image pieceImage getImage currentPiece int pieceHeight pieceImage getHeight null dou
  • Android 游戏偶尔出现延迟

    我正在用 Java 制作一个简单的 Android 游戏 我注意到每 20 40 秒就会出现一些烦人的延迟 首先 我认为它们是由垃圾收集器引起的 但当我检查 LogCat 时 我发现游戏滞后时没有垃圾收集 每当游戏开始滞后时 我都会标记日志
  • 强制 Java 最低版本以“java -version:”运行在 Windows 上不起作用

    我想强制应用程序运行的 JVM 最低版本为 1 6 或更高版本 即 1 6 我的理解是 您可以使用 version 命令行参数来执行此操作 我尝试了一下 在Linux下似乎可以正常工作 但在Windows下却不行 LINUX 我在 Linu
  • 在java中将DataURL图像转换为图像文件

    我在我的 java servlet 中接收图像 DataURL 它看起来像 data image jpeg base64 9j 4AAQSkZJRgABAQAAAQABAA 我需要将其另存为图像文件 我该怎么做 The simplest w
  • 反应式 Spring Webflux REST 控制器内部重定向

    我正在为 spring 反应项目创建简单的控制器服务器 在设置重定向到另一个位置时 我在调用时发现错误http localhost 8080 There was an unexpected error type Internal Serve
  • 两条腿的 OAuth 和 Gmail Atom feed

    我们正在尝试让 2 legged OAuth 与 Gmail Atom feed 一起使用 我们使用 John Kristian Praveen Alavilli 和 Dirk Ba lfanz 贡献的 Java 库 http oauth
  • JFrame Glasspane 也优于 JDialog,但不应该

    我有一个带有 Glasspane 的 JFrame 未装饰 该框架打开一个 JDialog 也未装饰 也有一个 glassPane 并隐藏自身 setVisible false Glasspanes 通过 setGlassPane 设置 对
  • Java 验证日期为 yyyyMMddHHmmss

    我想在java中验证给定的日期格式为yyyyMMddHHmmss 状况 应符合格式 yyyyMMddHHmmss 它应该验证当前日期 它应该验证与当前小时有 3 小时或 3 小时差异的小时数 如果满足所有三个条件 Java 方法应返回 tr
  • 更新分页。是否可以?

    他们是否存在一些方法来处理更新分页 例如我有 100 行类型 Id private Integer id Column private boolean flag Column private Date last 一开始它们看起来像 id f
  • 如何列出Resources文件夹中的所有文件(java/scala)

    我正在编写一个函数 需要访问资源中的文件夹 并循环遍历所有文件名 如果这些文件符合条件 则加载这些文件 new File getClass getResource images sprites getPath listFiles 返回空指针
  • Retrofit 2.0:预期为 BEGIN_OBJECT,但在第 1 行第 1 列路径 $ [重复] 处为 STRING

    这个问题在这里已经有答案了 我在邮递员上传递了更新用户请求并获得了成功的响应 参见图片 现在当我尝试使用 Retrofit 2 在我的应用程序中执行相同操作时 出现错误 com google gson JsonSyntaxException
  • 使用 PDFBox 在 Android 中创建 PDF

    我正在尝试通过我的 Android 应用程序创建 PDFPDFBoxapi 但出现以下错误 java lang NoClassDefFoundError org apache pdfbox pdmodel PDDocument 我已经将以下

随机推荐

  • 彩色动画内容演示器

    我无法在 ContentPresenter NormalTextDay 中创建动画或自定义颜色 此错误出现在我的 XAML 中 System Windows Media Animation ColorAnimation 动画对象无法用于对属
  • 需要在 Apache 上允许编码斜杠

    我目前正在尝试将 URL 放入 URL 中 例如 http example com url http 3A 2F 2Fwww url2 com 我知道我必须对 URL 进行编码 我已经这样做了 但现在我得到了404从服务器而不是我的应用程序
  • 对 JTable 进行排序会导致 NullPointerException

    我有一个 JTable 当单击相应的按钮时 它开始填充在后台进行的文件树遍历的结果 这很好用 然后我决定对表格进行排序 经过一番阅读后 我创建了一个 TableRowSorter 并设置表来使用它 它似乎有效 但经过仔细检查 我发现一些文件
  • Bing 地图 API 与 Android 应用程序的集成程度如何?

    首先我想问一下 你能整合吗 Bing Maps在 Android 应用程序中 其次 如果可以的话有什么好处Bing已经结束Google Maps API反之亦然 Updates This Android SDK v1 5现已弃用 看到这个链
  • PreparedStatement 如何避免或防止 SQL 注入?

    我知道PreparedStatements 可以避免 防止SQL 注入 它是如何做到的 使用PreparedStatements 构造的最终表单查询是字符串还是其他形式 考虑做同一件事的两种方法 PreparedStatement stmt
  • Windows 批处理文件中的传递、转义和识别特殊字符

    我编写了一个脚本 它会遍历输入字符串的每个字符 并根据我需要执行不同操作的字符 只要我的输入不包含任何空格或双引号字符 这种方法就可以很好地工作 我知道我必须转义特殊字符 但由于某种原因 我似乎对空格和双引号做错了 如果我使用参数 ab c
  • 打印图像的实际尺寸

    嗨 朋友们 我想打印我生成的图片 我使用以下代码 Printer BeginDoc Printer Canvas Draw 0 0 img1 Picture Bitmap Printer EndDoc 它可以工作 但它打印的图像非常小 我如
  • 通过序数索引访问红黑树

    我有一棵红黑树 二叉树 所有叶子都在2层以内 我可以浏览节点 向左 向右或父节点 我知道节点的全部数量 我必须找到树中第 N 个最小的元素 有没有比 O n 更快的方法 有什么通过索引优化访问的想法吗 在每个节点 X 中 您应该存储以 X
  • 如何确定文件对于 *nix 上的进程是否是只读的? [复制]

    这个问题在这里已经有答案了 使用 stat 函数 我可以获得以下内容的读 写权限 owner user other 但这不是我想要的 我想知道我的进程 即我正在编写的应用程序 的文件的读 写权限 仅当我知道我的进程是否作为文件的所有者 用户
  • 从 BigQuery 将数据导出到 GCS - 拆分文件大小控制

    我目前正在将数据从 Bigquery 导出到 GCS 存储桶 我使用以下查询以编程方式执行此操作 query request bigquery service jobs DATASET NAME PROJECT ID DATASET ID
  • TYPO3:存储库->findAll() 不起作用

    我正在构建一个带有后端模块的扩展 当我打电话给findAll 方法它返回一个 QueryResult 对象 我尝试用以下方法检索对象查找按Uid 并且它确实有效 我在打字稿中设置了存储pid plugin tx hwforms persis
  • VS2010(CUDA)中导出DLL的问题

    我在构建 DLL 解决方案时遇到了麻烦 我正在制作用于 LabVIEW 2010 的 DLL 以便具有 CUDA 功能 但是 我想要导出的每一个函数都收到链接器错误 LNK2019 include LVCUDA h include C Pr
  • Python 与 MS SQL - 截断输出

    我尝试从 Linux 盒子使用 python 连接到 MSSQL DB Python 2 7 乌班图11 04 我收到的输出被截断为 500 个字符 请参阅下面的脚本和配置 怎么解决呢 我认为问题出在 ODBC 驱动程序中或附近 代码 py
  • 无法使用 RJB gem 将应用程序部署到 Heroku

    我已经设置了 JAVA HOME 变量 heroku config add JAVA HOME usr lib jvm java 6 openjdk 检查 heroku 配置是否显示此变量的值 然后推 git push heroku mas
  • 当使用源代码签入依赖 jar 时,使用 Maven 是否仍然有意义?

    我们将所有源代码的依赖第三方 JAR 与我们的源代码一起检查到源代码管理中 需要时 我们手动下载第三方 JAR 的更新 并将那些处于源代码控制中的 JAR 替换为较新的版本 我们还没有感觉到需要使用 Maven 因为这个过程对我们来说似乎足
  • 无法加载文件或程序集“xxx.Data”该进程无法访问该文件,因为它正在被另一个进程使用

    从今天开始 我在一个我已经工作了几个月并且一直有效的项目中遇到了这个错误 我尝试清理解决方案并重建 并且构建工作完美 我尝试重新启动 VS 和 PC 但没有任何效果 所以问题不在代码中 无法加载文件或程序集 xxx Data 或其依赖项之一
  • 如何记录严重级别的事件日志?

    我想将事件查看器中的条目记录为 关键 但没有关联的事件日志类型 System Diagnostics EventLog WriteEntry ApplicationName message System Diagnostics EventL
  • 获取指定时区的日期时间,无论计算机中设置的日期时间如何

    我想打印时区的日期时间 Asia Kathmandu 我使用了以下代码 import datetime pytz tz pytz timezone Asia Kathmandu ktm now datetime datetime now t
  • 将 Http 请求与其余更新集成

    我正在使用以下模型制作一个简单的 Elm 应用程序 type alias Model num Float str String list List Float serverResponse String 我正在遵循 Todo MVC 示例
  • 如何正确地将 MouseHandler 添加到我的 JFreeChart-FX 以从左向右拖动图表

    我设法使用创建了烛台图JFreeChart FX并使用显示它fxgraphics2dAPI 但我对如何与我的图表进行任何交互感到非常困惑 并且需要一些帮助 如果您在正确的方向上提供任何帮助 我将非常感激 我开始于this例如 获取我的初始图