对齐多个 XYChart 的 X 轴

2023-11-30

我有两个XYChart我想垂直对齐显示。

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

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

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

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

为了重现性,这里是一个由Oracle 的教程:

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。

Edit:正如答案中所建议的,我已将这个问题的范围缩小到对齐 x 轴的问题。询问尺码问题here.


这是一个专门布局的快速截图

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

这不是生产质量,只是为了初学者如何做到这一点:)

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

对齐多个 XYChart 的 X 轴 的相关文章

  • 图像仅在 iPhone x 上拉伸

    我目前正在设计和构建一个 html 和 css 网站 遇到了一个小问题 我使用 chrome 开发工具检查了响应能力 根据手机和平板电脑的大小调整窗口大小 一切看起来都很好 然而 现在我在 iPhone X 上检查了该网站 图像全部垂直拉伸
  • 当线程完成这项工作时,我是否需要使用 JavaFX 中的线程和任务在后台运行某些内容?

    我正在使用一个线程定期运行三秒的背景动画 我改编了用 Swing 编写的线程演示示例中的相关代码并使用 它取代了一个不太工作的早期版本 该版本同时使用了线程和任务 我的程序在播放视频或运行动画时停止 挂起线程 并在结束视频或动画时启动新线程
  • 更改在不同场景中输入的新场景中的标签文本(javafx)

    我正在尝试更改标签中的文本 该文本是在不同场景的文本字段中输入的文本 我制作了 2 个 FXML 文件 第一个包含一个文本字段和 确定 按钮 第二个包含一个标签 带有文本 标签 我的目标是在文本字段中输入文本 当我按 确定 gt 打开新场景
  • 如何在JavaFX中为TextArea设置圆角?

    我需要在 TextArea 上有圆角 但它看起来有点奇怪 看起来 有些内层也应该有相同半径的圆角 但是哪一个呢 我使用这个CSS text area fx background color dbb1b1 fff0f0 fx backgrou
  • 为 tableView JavaFx 中没有第一个(行数)的列设置 CONSTRAINED_RESIZE_POLICY

    我的 tableView 的第一列为行号 我想为没有第一个列的所有列设置 CONSTRAINED RESIZE POLICY I made First column implementation column setPrefWidth 40
  • Android:图形布局不起作用 - 不显示任何内容

    我的情况是 我曾经制作过一个android项目 2 2版本 但很快需要格式化我的电脑 格式化后 我再次下载了 eclipse 但是当我导入项目时 我无法使用 xml 的 图形布局 菜单 它没有向我显示如下图所示的任何内容 http img5
  • JavaFX 可以在 Android 上运行吗?

    如果不这样做那就太可惜了 因为这将使 Android 应用程序看起来更有吸引力 现在还不行 要让它发挥作用将是一项艰巨的任务 Android 不具备典型桌面 JRE 所具备的所有库 尽管Android是开源的并且它会运行任何可以编译为Dal
  • 在文本基线上水平对齐块

    我有以下 HTML 代码
  • 使用translateX()和translateY()时,窗格布局内的JavaFX文本与其他元素重叠

    下图是对正在发生的情况的描述 我有一个Pane其中包含一个Text我正在使用下面的代码来制作marquee like effect of the Text 所以当Pane没有足够的空间来显示文本 动画正在开始 文本必须来回移动 以便用户可以
  • JavaFX 多线程 - 连接线程不会更新 UI

    我正在尝试创建一个加载程序对话框 用户可以在其中知道程序正在加载所请求的内容并且程序正在按预期运行 但正因为如此 我需要join 解析器线程和之前继续主线程 这使得对话框空白 解析器任务 java public class ParserTa
  • 需要解释 android 布局语法

    这是布局文件中的一行
  • SwiftUI 表单中的动态行高

    我正在向 SwiftUI 表单添加控件以帮助用户输入数据 并限制条目 尽管 Forms 有很多值得喜欢的地方 但我发现在该容器之外运行良好的东西在容器内却会发生非常意想不到的事情 并且如何弥补这一点并不总是显而易见的 计划是将数据字段显示为
  • 找不到布局变小的原因

    这是我的代码 几乎按预期工作 在讨论问题之前 请先查看代码 请原谅我的代码很长 但这可以像 java 类一样粘贴 我使用 NETBEANS JForm 设计器来获取 GUI package test import java awt even
  • Partial、Layout、Template 渲染问题

    情况 因此 当我访问页面时 我希望能够将布局应用到部分 我想要三个具有相同布局的部分 现在 我正在尝试使用以下命令来执行此操作 where shared services essay是这样的 p blah p div blah div
  • 如何在 JavaFX 中对单选按钮的最大可选复选框进行限制?

    请看下面的图片 您就会了解我的应用程序的布局 我希望能够动态选择多少CheckBox 启用下拉菜单 是可选的 固定数量 我想用这 3 个人来实现这个目标RadioButton 在垂直模式下全部 4CheckBox必须选择 不少于 在混合模式
  • JavaFX 按钮不会禁用

    我有一个可能需要几秒钟到几分钟的任务 当我单击按钮执行该任务时 它会运行该任务但并不总是禁用按钮A和启用按钮B 这是我正在使用的代码 FXML public void onExecute ActionEvent event btnExecu
  • 在模块路径上使用 OpenJFX 11 JMODS 在 JDK 11 上运行 javafx 示例

    我已经从 OpenJFX 项目下载了 JavaFX Jmod 文件并将它们放在目录中G openjfx javafx jmods 11 我使用的是 OpenJDK 11 其中没有 JavaFX jmodJAVA HOME jmods即它不附
  • JavaFX 拖放无法正常工作

    我在网格窗格中使用两个 Imageview 进行拖放测试 我的问题是 当我完成拖放并将目标图像视图移动到源图像视图并释放鼠标时 我错误地最终显示了 img2 中的图片 而不是 img1 中的图片 当我注释掉 setOnDragExited
  • 我在使用 JavaFX 绘制十字时遇到问题

    我正在尝试编写代码 在网格上对角绘制 3 个形状 前两个形状是正方形和圆形 我能做到 然而 第三种形状让我有些悲伤 我应该画一个十字 T 版本 而不是 X 每次我写出代码时 它看起来就像一个侧面 我知道我只是错过了一些简单的东西 但我真的很
  • 如何创建一个显示 Spinners 的 x 和 y 值的表格?

    我想创建一个位于图表右侧的表格 其中显示 2 列 x 和 y 值已输入到xSpin and ySpin旋转器 我已经画了一张我想要桌子放置的位置的图 我尝试过在网格窗格布局中使用文本框来创建表格并将值直接输入到文本框网格中 但是我无法将它们

随机推荐