压缩/扩展 JavaFX 2 数据图表
Posted
技术标签:
【中文标题】压缩/扩展 JavaFX 2 数据图表【英文标题】:Compressing/Expanding JavaFX 2 data chart 【发布时间】:2012-07-16 07:01:50 【问题描述】:有一个 XY 折线图我想通过鼠标左键单击压缩/扩展 X 和 Y 轴的数据可视化,按住并拖动左/右和上/下。
这是一个图表示例
这是绘制样本数据的代码
public class BaseXYChart extends Application
@Override
public void start(Stage stage)
stage.setTitle("Linear plot");
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis(1, 22, 0.5);
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis)
@Override
public String toString(Number object)
return String.format("%7.2f", object);
);
final LineChart<String, Number>lineChart = new LineChart<String, Number>(xAxis, yAxis);
lineChart.setCreateSymbols(false);
lineChart.setAlternativeRowFillVisible(false);
lineChart.setLegendVisible(false);
XYChart.Series series1 = new XYChart.Series();
series1.getData().add(new XYChart.Data("Jan", 1));
series1.getData().add(new XYChart.Data("Feb", 1.5));
series1.getData().add(new XYChart.Data("Mar", 2));
series1.getData().add(new XYChart.Data("Apr", 2.5));
series1.getData().add(new XYChart.Data("May", 3));
series1.getData().add(new XYChart.Data("Jun", 4));
series1.getData().add(new XYChart.Data("Jul", 6));
series1.getData().add(new XYChart.Data("Aug", 9));
series1.getData().add(new XYChart.Data("Sep", 12));
series1.getData().add(new XYChart.Data("Oct", 15));
series1.getData().add(new XYChart.Data("Nov", 20));
series1.getData().add(new XYChart.Data("Dec", 22));
BorderPane pane = new BorderPane();
pane.setCenter(lineChart);
Scene scene = new Scene(pane, 800, 600);
lineChart.getData().addAll(series1);
stage.setScene(scene);
stage.show();
public static void main(String[] args)
launch(args);
我怎样才能做到这一点?我在任何地方都没有找到任何示例!
谢谢。
添加图片
鼠标左键按下并在Y轴上从上到下拖动后的结果
X 轴通过鼠标左/右键拖动获得压缩线数据的结果应该相同
【问题讨论】:
【参考方案1】:如果我正确理解了您的问题,也许您可以使用类似以下的方法,根据在轴上的单击和拖动来调整图表的大小。
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.event.EventHandler;
import javafx.scene.*;
import javafx.scene.chart.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Effect;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class DraggableAxisResizableChart extends Application
private static final int UNDEFINED = -1;
public static void main(String[] args) launch(args);
@Override public void start(Stage stage)
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Number, Number> chart = new LineChart(
xAxis, yAxis,
FXCollections.observableArrayList(
new XYChart.Series("April", FXCollections.observableArrayList(
new XYChart.Data(0, 4), new XYChart.Data(1, 10), new XYChart.Data(2, 18), new XYChart.Data(3, 15)
))
)
);
chart.setPrefSize(400, 300);
chart.setMaxSize(400, 300);
makeXAxisDraggable(xAxis, chart);
makeYAxisDraggable(yAxis, chart);
StackPane layout = new StackPane();
layout.getChildren().add(chart);
stage.setScene(new Scene(layout, 800, 600));
stage.show();
private void makeXAxisDraggable(final NumberAxis xAxis, final LineChart<Number, Number> chart)
final Delta d = new Delta();
xAxis.setOnMouseDragged(new EventHandler<MouseEvent>()
@Override public void handle(MouseEvent event)
if (d.x == UNDEFINED)
d.x = event.getSceneX();
d.y = event.getSceneY();
else
chart.setMaxHeight(
chart.getPrefHeight() * (
(chart.getPrefHeight() + (event.getSceneY() - d.y) * 2) / chart.getPrefHeight()
)
);
);
xAxis.setOnMouseReleased(new EventHandler<MouseEvent>()
@Override public void handle(MouseEvent event)
d.x = UNDEFINED; d.y = UNDEFINED;
chart.setPrefSize(chart.getMaxWidth(), chart.getMaxHeight());
);
addMouseoverGlow(xAxis);
private void makeYAxisDraggable(final NumberAxis yAxis, final LineChart<Number, Number> chart)
final Delta d = new Delta();
yAxis.setOnMouseDragged(new EventHandler<MouseEvent>()
@Override public void handle(MouseEvent event)
if (d.x == -1)
d.x = event.getSceneX();
d.y = event.getSceneY();
else
chart.setMaxWidth(
chart.getPrefWidth() * (
(chart.getPrefWidth() - (event.getSceneX() - d.x) * 2) / chart.getPrefWidth()
)
);
);
yAxis.setOnMouseReleased(new EventHandler<MouseEvent>()
@Override public void handle(MouseEvent event)
d.x = UNDEFINED; d.y = UNDEFINED;
chart.setPrefSize(chart.getMaxWidth(), chart.getMaxHeight());
);
addMouseoverGlow(yAxis);
// create a glow feedback effect on a node when the mouse is hovered over it.
private void addMouseoverGlow(final Node n)
final Effect glow = new DropShadow(10, Color.GOLDENROD);
n.setOnMouseEntered(new EventHandler<MouseEvent>()
@Override public void handle(MouseEvent event)
n.setEffect(glow);
);
n.setOnMouseExited(new EventHandler<MouseEvent>()
@Override public void handle(MouseEvent event)
n.setEffect(null);
);
// records a relative point location.
class Delta double x = UNDEFINED, y = UNDEFINED;
替代实现可以在节点上使用比例。
上面的实现在调整图形大小时会留下轻微的鬼影痕迹,因此如果示例证明有用,您可能希望以某种方式修复它。
【讨论】:
谢谢jewelsea,你的作品很棒,但我认为我没有正确解释我需要实现的目标:一旦绘制数据(对于数据,我指的是绘制的线数据),通过鼠标左键单击,保持按下并在 X 轴上向左/向右拖动线条本身应展开/压缩(即放大),而图表保持相同的 800,600 尺寸。场景不会随着尺寸而改变,只有我们会改变线图。将尝试添加图片以便更清晰 以为我遗漏了一些东西 ;-) 我想你可能想研究一下在拖动检测时设置 range。拖动检测逻辑应该类似于我提供的示例,但您将缩放最大/最小范围值而不是图表大小。 感谢jewelsea,我会根据您的建议尝试修改您的代码以上是关于压缩/扩展 JavaFX 2 数据图表的主要内容,如果未能解决你的问题,请参考以下文章
如何使用ObservableList在Javafx中创建折线图的BarChart
Visual Studio 扩展工具使用 ComponentOne迷你图控件,进行可视化数据趋势分析