Question:
For a scientific desktop application, it became necessary to use the JFreeChart graphics library specifically for AWT, since under java fx with a large amount of displayed data, the application slows down, but at the same time, for the rest of the interface, I want to use the capabilities of java fx. In this connection, an idea arose for discussion: What if we make a separate component for the graph on a fast-working library for AWT and use some means of interprocess communication: rmi, ws, rest to link it with the main application on java fx? What are the pitfalls in this approach?
Answer:
Within the framework of the current question, there is no need to complicate the architecture, since JavaFX
supports displaying JComponent
(see SwingNode )
An example for your situation:
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import javax.swing.*;
import java.awt.*;
public class Main extends Application {
public void start(Stage primaryStage) throws Exception {
final SwingNode swingNode = new SwingNode();
SwingUtilities.invokeLater(() -> swingNode.setContent(createChartPanel()));
primaryStage.setScene(new Scene(new BorderPane(swingNode)));
primaryStage.show();
}
private ChartPanel createChartPanel() {
XYDataset dataset = createDataset();
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
chartPanel.setBackground(Color.white);
return chartPanel;
}
private XYDataset createDataset() {
XYSeries series = new XYSeries("2016");
series.add(18, 567);
series.add(20, 612);
series.add(25, 800);
series.add(30, 980);
series.add(40, 1410);
series.add(50, 2350);
XYSeriesCollection dataset = new XYSeriesCollection();
dataset.addSeries(series);
return dataset;
}
private JFreeChart createChart(XYDataset dataset) {
JFreeChart chart = ChartFactory.createXYLineChart(
"Average salary per age",
"Age",
"Salary (€)",
dataset,
PlotOrientation.VERTICAL,
true,
true,
false
);
XYPlot plot = chart.getXYPlot();
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
renderer.setSeriesPaint(0, Color.RED);
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
plot.setRenderer(renderer);
plot.setBackgroundPaint(Color.white);
plot.setRangeGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.BLACK);
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.BLACK);
chart.getLegend().setFrame(BlockBorder.NONE);
chart.setTitle(new TextTitle("Average Salary per Age",
new Font("Serif", java.awt.Font.BOLD, 18)
)
);
return chart;
}
}
well, and accordingly, do not forget to connect the library:
<dependency>
<groupId>jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.13</version>
</dependency>
PS: if your application slows down with this approach, then:
- Try looking towards the native JavaFX charts (see manual )
- If there is really a lot of data, then perhaps the problem can be solved by improving the hardware. Resource monitoring will help you determine this.
- If points 1 and 2 did not help, then for help you will need a sample application (which you can run and see that the program really slows down). According to the data for the load.
PS2: In the third case, it is not necessary to show your entire application (if it is prohibited by any policy), it is enough to simulate this situation in a separate new program.