无限JavaFX坐标系窗格
我需要编写一个自定义窗格,其行为类似于无限二维笛卡尔坐标系。第一次显示时,我希望0,0位于窗格的中心。用户应该能够通过按住鼠标左键并拖动来导航窗格。它需要有放大和缩小的能力。我还必须能够在特定坐标处放置节点 当然,我知道这是一个非常具体的控件,我不会要求任何人给我一步一步的说明或为我编写。无限JavaFX坐标系窗格,java,javafx,custom-controls,coordinate-systems,jfreechart,Java,Javafx,Custom Controls,Coordinate Systems,Jfreechart,我需要编写一个自定义窗格,其行为类似于无限二维笛卡尔坐标系。第一次显示时,我希望0,0位于窗格的中心。用户应该能够通过按住鼠标左键并拖动来导航窗格。它需要有放大和缩小的能力。我还必须能够在特定坐标处放置节点 当然,我知道这是一个非常具体的控件,我不会要求任何人给我一步一步的说明或为我编写。 我刚刚接触JFX自定义控件的世界,不知道如何解决这个问题,尤其是整个infinity问题。这并不像您想象的那么难实现。只需从一个简单的窗格开始。这已经为您提供了infinte坐标系。与你的要求不同的是,点0/
我刚刚接触JFX自定义控件的世界,不知道如何解决这个问题,尤其是整个infinity问题。这并不像您想象的那么难实现。只需从一个简单的窗格开始。这已经为您提供了infinte坐标系。与你的要求不同的是,点0/0在左上角而不是在中间。可以通过对窗格应用“平移”变换来修复此问题。然后,通过将相应的鼠标侦听器添加到窗格中,可以以类似的方式实现缩放和平移。一种方法是按照建议,在视图中呈现任意内容。相应的
GraphicsContext
可最大限度地控制坐标。作为一个具体示例,使用渲染图表,其ChartViewer
包含扩展Canvas
的ChartCanvas
。从这一点开始,下面的变化将域轴设置为在向三个系列添加相应点后跨越以零为中心的间隔。使用鼠标滚轮或关联菜单进行缩放;有关缩放和平移的详细信息,请参阅此相关文档
for (double t = -3; t <= 3; t += 0.5) {
series.add(t, Math.sin(t) + i);
}
…
xAxis.setRange(-Math.PI, Math.PI);
…
plot.setDomainPannable(true);
for(double t=-3;t谢谢!您引导我走上了正确的道路。我最终在滚动窗格中使用了一个窗格。我禁用了两个滚动条,因此只能通过平移来导航滚动窗格。我利用了您的一些想法。感谢您指出了这么多示例并花时间编写了这么详细的答案!
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.LegendItemEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.fx.ChartViewer;
import org.jfree.chart.fx.interaction.ChartMouseEventFX;
import org.jfree.chart.fx.interaction.ChartMouseListenerFX;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* @see https://stackoverflow.com/a/44967809/230513
* @see https://stackoverflow.com/a/43286042/230513
*/
public class VisibleTest extends Application {
@Override
public void start(Stage stage) {
XYSeriesCollection dataset = new XYSeriesCollection();
for (int i = 0; i < 3; i++) {
XYSeries series = new XYSeries("value" + i);
for (double t = -3; t <= 3; t += 0.5) {
series.add(t, Math.sin(t) + i);
}
dataset.addSeries(series);
}
NumberAxis xAxis = new NumberAxis("domain");
xAxis.setRange(-Math.PI, Math.PI);
NumberAxis yAxis = new NumberAxis("range");
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, true);
renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
JFreeChart chart = new JFreeChart("Test", plot);
ChartViewer viewer = new ChartViewer(chart);
viewer.addChartMouseListener(new ChartMouseListenerFX() {
@Override
public void chartMouseClicked(ChartMouseEventFX e) {
ChartEntity ce = e.getEntity();
if (ce instanceof XYItemEntity) {
XYItemEntity item = (XYItemEntity) ce;
renderer.setSeriesVisible(item.getSeriesIndex(), false);
} else if (ce instanceof LegendItemEntity) {
LegendItemEntity item = (LegendItemEntity) ce;
Comparable key = item.getSeriesKey();
renderer.setSeriesVisible(dataset.getSeriesIndex(key), false);
} else {
for (int i = 0; i < dataset.getSeriesCount(); i++) {
renderer.setSeriesVisible(i, true);
}
}
}
@Override
public void chartMouseMoved(ChartMouseEventFX e) {}
});
stage.setScene(new Scene(viewer));
stage.setTitle("JFreeChartFX");
stage.setWidth(640);
stage.setHeight(480);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}