gpt4 book ai didi

java - 如何获得对 JavaFX 图表的低级别访问以便绘制图像?

转载 作者:行者123 更新时间:2023-12-01 19:30:51 25 4
gpt4 key购买 nike

我想在折线图后面绘制一个图像,以便在图像上绘制任何网格和线条。看来 LineChart 需要向 Canvas 公开一些较低级别的访问器,以便可以完成此操作。

public class ChartBgImageTest {
public ChartBgImageTest() {

final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis(1, 21, 0.1);
final LineChart<String, Number> lineChart = new LineChart<String, Number>(xAxis, yAxis);

BufferedImage bufferedImage = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration()
.createCompatibleImage(600, 400);


BufferedImage img = new BufferedImage(600, 400, BufferedImage.TYPE_INT_RGB);
img.createGraphics().fillRect(0, 0, 50, 50);
// Fill img code here

Graphics g2d = bufferedImage.createGraphics();

g2d.drawImage(img, 0, 0, null);

// TODO How to draw the img to lineChart background.
// So that any grids or lines on the chart are drawn above the img.

}
}

最佳答案

javafx.scene.chart 包中的图表不使用 Canvas 来绘制图表。相反,他们使用场景图。在您的问题中,您正在动态创建图像,但假设您已经创建了图像(可能作为嵌入式资源),则可以使用 CSS 将图像添加到图表的背景中。查看 JavaFX CSS Reference GuideXYChart 部分,您将看到其中一个子结构被标记为 chart-plot-background 并且是一个 Region,这意味着可以通过 CSS 将背景图像应用到它。例如:

App.java:

import java.util.Random;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage;

public class App extends Application {

@Override
public void start(Stage primaryStage) {
var chart = new LineChart<>(new NumberAxis(), new NumberAxis(), createChartData());
chart.getXAxis().setLabel("X");
chart.getYAxis().setLabel("Y");

var scene = new Scene(chart, 1000, 650);
scene.getStylesheets().add(getClass().getResource("/style.css").toString());

primaryStage.setScene(scene);
primaryStage.show();
}

private static ObservableList<Series<Number, Number>> createChartData() {
var random = new Random();

var chartData = FXCollections.<Series<Number, Number>>observableArrayList();
for (int i = 1; i <= 3; i++) {
var data = FXCollections.<Data<Number, Number>>observableArrayList();
for (int j = 0; j <= 15; j++) {
data.add(new Data<>(j, random.nextInt(250)));
}
chartData.add(new Series<>("Series #" + i, data));
}
return chartData;
}
}

样式.css:

.chart-plot-background {
-fx-background-image: url(/* your URL */);
-fx-background-size: cover;
}

这只会绘制实际图表内容(即数据)后面的图像。轴、图例和周围空间后面不会有图像。如果您希望整个图表具有背景图像,那么您可以利用所有图表实现都继承自的Chart这一事实,它是从Region扩展而来的>。将 CSS 更改为:

.chart {
-fx-background-image: url(/* your URL */);
-fx-background-size: cover;
}

.chart-plot-background,
.chart-legend {
-fx-background-color: null;
}

如果您想要在绘图背景和整个图表之间添加一些内容,您可以将图像添加到 .chart-content (记录为 here )。

<小时/>

如果您必须留在代码内(例如,因为您正在动态创建图像),那么您必须获取对必要的区域的引用。为此,您可以使用 Node#lookup(String) 。但请注意,您可能需要等到图表在屏幕上呈现后才调用 lookup,因为可能尚未创建所需的后代节点并将其添加到场景图中(此对于控件来说尤其如此)。

import java.util.Random;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.image.Image;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundImage;
import javafx.scene.layout.BackgroundPosition;
import javafx.scene.layout.BackgroundSize;
import javafx.scene.layout.Region;
import javafx.stage.Stage;

public class App extends Application {

@Override
public void start(Stage primaryStage) {
var chart = new LineChart<>(new NumberAxis(), new NumberAxis(), createChartData());
chart.setTitle("Example Chart");
chart.getXAxis().setLabel("X");
chart.getYAxis().setLabel("Y");

var scene = new Scene(chart, 1000, 650);

primaryStage.setScene(scene);
primaryStage.show();

var plotBackground = (Region) chart.lookup(".chart-plot-background");
plotBackground.setBackground(
new Background(
new BackgroundImage(
new Image(/* your URL */),
null,
null,
BackgroundPosition.CENTER,
new BackgroundSize(0, 0, false, false, true, false))));
}

private static ObservableList<Series<Number, Number>> createChartData() {
var random = new Random();

var chartData = FXCollections.<Series<Number, Number>>observableArrayList();
for (int i = 1; i <= 3; i++) {
var data = FXCollections.<Data<Number, Number>>observableArrayList();
for (int j = 0; j <= 15; j++) {
data.add(new Data<>(j, random.nextInt(250)));
}
chartData.add(new Series<>("Series #" + i, data));
}
return chartData;
}
}

请注意,您不能直接通过 JavaFX API 使用 BufferedImage。如果您需要在代码中实际绘制Image,您有几个选择:

关于java - 如何获得对 JavaFX 图表的低级别访问以便绘制图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59792702/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com