gpt4 book ai didi

javafx - 对齐多个 XYCharts 的 X 轴

转载 作者:行者123 更新时间:2023-12-04 03:01:09 25 4
gpt4 key购买 nike

我有两个要垂直对齐显示的 XYChart

两个图共享相同的x轴,但它们使用不同的数据集,这些值的数量级不同。这使得 y 轴标签的大小非常不同。最后,两个 x 轴不再对齐。

我的目标是对齐那些 x 轴。

一个提议的解决方案通过旋转 y 轴标签提供了一种解决方法,使标签宽度相同。虽然这有效(我感谢贡献者的回答),但这并不完全令人满意:只要我有不同大小的图例,我就会面临同样的问题(参见 R 中的 this question,其中有几个令人满意的解决方案在哪里找到的)。

我真的很想保持标签方向不变并“玩”图表组件的大小。

为了可重复性,这里是一个从 Oracle's tutorial 构建的示例:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class Test extends Application {

@Override
public void start(Stage stage) {
stage.setTitle("Line Chart Sample");
final CategoryAxis xAxis1 = new CategoryAxis();
final NumberAxis yAxis1 = new NumberAxis();
xAxis1.setLabel("Month");
final LineChart<String, Number> lineChart1 =
new LineChart<>(xAxis1, yAxis1);

final CategoryAxis xAxis2 = new CategoryAxis();
xAxis2.setLabel("Month");
final NumberAxis yAxis2 = new NumberAxis();
final LineChart<String, Number> lineChart2 =
new LineChart<>(xAxis2, yAxis2);

lineChart1.setTitle("Charts");
lineChart1.setLegendVisible(false);
lineChart2.setLegendVisible(false);

XYChart.Series series1 = new XYChart.Series();
series1.setName("Portfolio 1");

series1.getData().add(new XYChart.Data("Jan", 23));
series1.getData().add(new XYChart.Data("Feb", 14));
series1.getData().add(new XYChart.Data("Mar", 15));
series1.getData().add(new XYChart.Data("Apr", 24));
series1.getData().add(new XYChart.Data("May", 34));
series1.getData().add(new XYChart.Data("Jun", 36));
series1.getData().add(new XYChart.Data("Jul", 22));
series1.getData().add(new XYChart.Data("Aug", 45));
series1.getData().add(new XYChart.Data("Sep", 43));
series1.getData().add(new XYChart.Data("Oct", 17));
series1.getData().add(new XYChart.Data("Nov", 29));
series1.getData().add(new XYChart.Data("Dec", 25));

XYChart.Series series2 = new XYChart.Series();
series2.setName("Portfolio 2");
series2.getData().add(new XYChart.Data("Jan", 330000));
series2.getData().add(new XYChart.Data("Feb", 340000));
series2.getData().add(new XYChart.Data("Mar", 250000));
series2.getData().add(new XYChart.Data("Apr", 440000));
series2.getData().add(new XYChart.Data("May", 390000));
series2.getData().add(new XYChart.Data("Jun", 160000));
series2.getData().add(new XYChart.Data("Jul", 550000));
series2.getData().add(new XYChart.Data("Aug", 540000));
series2.getData().add(new XYChart.Data("Sep", 480000));
series2.getData().add(new XYChart.Data("Oct", 270000));
series2.getData().add(new XYChart.Data("Nov", 370000));
series2.getData().add(new XYChart.Data("Dec", 290000));

lineChart1.getData().addAll(series1);
lineChart2.getData().addAll(series2);

VBox vBox = new VBox();
vBox.addAll(lineChart1, lineChart2);

Scene scene = new Scene(gridPane, 800, 600);

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


public static void main(String[] args) {
launch(args);
}

}

结果如下:

enter image description here

是否可以控制图表组件的大小使两个x轴对齐?

我尝试更改首选的 y 轴和最小宽度,但它似乎不起作用。

我目前使用的是 Java 8。如有必要,可以迁移到 Java 9。

编辑:正如答案中所建议的,我已将此问题的范围缩小为对齐 x 轴的问题。问尺码问题here .

最佳答案

这是一个特殊布局的快速截图

  • 只关心 XYChart 类型的 child
  • 将它们垂直放置,它们之间的间距可配置
  • 将 yAxis 宽度调整为其 prefWidth,注意我们需要传入轴的实际高度(相对于典型的 -1)...花了我一段时间..
  • 将每个水平对齐,使 x 轴对齐并且 y 轴有足够的空间用于其标签

这不是生产质量,只是关于如何做的初学者:)

/**
* Lays out XYCharts vertically such that their x-axis are aligned and
* there's enough space to fully show the labels of all y-axis.
*
* @author Jeanette Winzenburg, Berlin
*/
public class VChartBox extends Pane {

protected void layoutChildren() {
Insets insets = getInsets();
double width = getWidth();
double height = getHeight();
// not entirely certain when to apply all the snaps, this is
// simply copied from vbox
double top = snapSpaceY(insets.getTop());
double left = snapSpaceX(insets.getLeft());
double bottom = snapSpaceY(insets.getBottom());
double right = snapSpaceX(insets.getRight());
double space = snapSpaceY(getSpacing());

double availableWidth = snapSpaceX(width - left - right);
List<XYChart> charts = getCharts();
if (charts.isEmpty()) return;
double heightPerChart = height / charts.size() - space;
OptionalDouble maxYAxisWidth = charts.stream()
.filter(chart -> chart.getYAxis() != null)
.mapToDouble(chart -> chart.getYAxis().prefWidth(heightPerChart))
.max();
double maxYWidth = maxYAxisWidth.orElse(0);
double remainingWidth = availableWidth - maxYWidth;
for (XYChart c : charts) {
Axis axis = c.getYAxis();
double axisWidth = axis != null ? axis.prefWidth(heightPerChart) : 0;
double axisOffset = maxYWidth - axisWidth;
double xOffset = axisOffset + left;
double chartWidth = remainingWidth + axisWidth;
c.resizeRelocate(xOffset, top, chartWidth, heightPerChart);
top += snapSpaceY(c.getHeight() + getSpacing());
}
}

protected List<XYChart> getCharts() {
return getChildren().stream().filter(child -> child instanceof XYChart)
.map(chart -> (XYChart) chart).collect(toList());
}

// properties
/**
* The amount of vertical space between each child in the vbox.
*
* @return the amount of vertical space between each child in the vbox
*/
public final DoubleProperty spacingProperty() {
if (spacing == null) {
spacing = new SimpleDoubleProperty(this, "spacing", 20) {
@Override
public void invalidated() {
requestLayout();
}

};
}
return spacing;
}

private DoubleProperty spacing;

public final void setSpacing(double value) {
spacingProperty().set(value);
}

public final double getSpacing() {
return spacing == null ? 0 : spacing.get();
}

@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(VChartBox.class.getName());
}

关于javafx - 对齐多个 XYCharts 的 X 轴,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49139565/

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