Charts JavaFX2绘制箭头

Charts JavaFX2绘制箭头,charts,line,javafx-2,Charts,Line,Javafx 2,此代码绘制一个简单的XYLine图表 import javafx.application.Application; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.sc

此代码绘制一个简单的XYLine图表

import javafx.application.Application;
import javafx.event.EventHandler;
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.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class XyChart extends Application {

@Override
public void start(Stage stage) {
   stage.setTitle("Line plot");

   final CategoryAxis xAxis = new CategoryAxis();
   final NumberAxis yAxis = new NumberAxis(1, 21,0.1);

   yAxis.setTickUnit(1);
   yAxis.setPrefWidth(35);
   yAxis.setMinorTickCount(10);

   yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis){
        @Override
    public String toString(Number object){
            String label;
            label = String.format("%7.2f", object.floatValue());
            return label;
    }
});
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", 4));
    series1.getData().add(new XYChart.Data("Mar", 2.5));
    series1.getData().add(new XYChart.Data("Apr", 5));
    series1.getData().add(new XYChart.Data("May", 6));
    series1.getData().add(new XYChart.Data("Jun", 8));
    series1.getData().add(new XYChart.Data("Jul", 12));
    series1.getData().add(new XYChart.Data("Aug", 8));
    series1.getData().add(new XYChart.Data("Sep", 11));
    series1.getData().add(new XYChart.Data("Oct", 13));
    series1.getData().add(new XYChart.Data("Nov", 10));
    series1.getData().add(new XYChart.Data("Dec", 20));

    BorderPane pane = new BorderPane();
    pane.setCenter(lineChart);          
    Scene scene = new Scene(pane, 800, 600);
    lineChart.setAnimated(false);
    lineChart.getData().addAll(series1);       

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

public static void main(String[] args) {
    launch(args);
}   
}
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.chart.CategoryAxis;
导入javafx.scene.chart.LineChart;
导入javafx.scene.chart.NumberAxis;
导入javafx.scene.chart.XYChart;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.BorderPane;
导入javafx.stage.stage;
公共类XyChart扩展应用程序{
@凌驾
公众假期开始(阶段){
舞台布景标题(“线条图”);
最终CategoryAxis xAxis=新CategoryAxis();
最终数字xis yAxis=新数字xis(1,21,0.1);
yAxis.setTickUnit(1);
yAxis.setPrefWidth(35);
yAxis.setMinorTickCount(10);
yAxis.setTickLabelFormatter(新编号Axis.DefaultFormatter(yAxis){
@凌驾
公共字符串toString(数字对象){
字符串标签;
label=String.format(“%7.2f”,object.floatValue());
退货标签;
}
});
最终线形图线形图=新线形图(xAxis,yAxis);
lineChart.setCreateSynumbles(false);
线形图.setAlternativeRowFillVisible(假);
线形图。setLegendVisible(假);
XYChart.Series系列1=新的XYChart.Series();
series1.getData().add(新的XYChart.Data(“Jan”,1));
series1.getData().add(新的XYChart.Data(“Feb”,4));
series1.getData().add(新的XYChart.Data(“Mar”,2.5));
series1.getData().add(新的XYChart.Data(“Apr”,5));
series1.getData().add(新的XYChart.Data(“May”,6));
series1.getData().add(新的XYChart.Data(“Jun”,8));
series1.getData().add(新的XYChart.Data(“Jul”,12));
series1.getData().add(新的XYChart.Data(“Aug”,8));
series1.getData().add(新的XYChart.Data(“Sep”,11));
series1.getData().add(新的XYChart.Data(“Oct”,13));
series1.getData().add(新的XYChart.Data(“Nov”,10));
series1.getData().add(新的XYChart.Data(“Dec”,20));
BorderPane=新的BorderPane();
窗格。设置中心(折线图);
场景=新场景(窗格,800600);
线形图。设置动画(假);
lineChart.getData().addAll(series1);
舞台场景;
stage.show();
}
公共静态void main(字符串[]args){
发射(args);
}   
}
我想在图表上画箭头,用鼠标左键点击按下并移动,如本例所示

如何做到这一点


谢谢大家。

您可以将鼠标处理程序添加到边框窗格中,并在鼠标移动时绘制箭头。 也许有更好的方法,但这就是我想到的:

将鼠标处理程序添加到边框窗格:

MouseHandler mh = new MouseHandler( pane );
pane.setOnMouseClicked( mh );
pane.setOnMouseMoved( mh );
处理程序类可以如下所示:

class MouseHandler implements EventHandler< MouseEvent > {
    private boolean gotFirst    = false;
    private Line    line, head1, head2;
    private Pane    pane;
    private double  x1, y1, x2, y2;
    double          phi         = Math.toRadians( 40 );
    double          barb        = 20;

    public MouseHandler( Pane pane ) {
        this.pane = pane;
    }

    @Override
    public void handle( MouseEvent event ) {
        if( event.getEventType() == MouseEvent.MOUSE_CLICKED ) {
            if( !gotFirst ) {
                x1 = x2 = event.getX();
                y1 = y2 = event.getY();
                line = new Line( x1, y1, x2, y2 );
                head1 = new Line( x2, y2, x2, y2 );
                head2 = new Line( x2, y2, x2, y2 );
                pane.getChildren().add( line );
                pane.getChildren().add( head1 );
                pane.getChildren().add( head2 );
                gotFirst = true;
            } else {
                line = null;
                gotFirst = false;
            }
        } else {
            if( line != null ) {
                x2 = event.getX();
                y2 = event.getY();
                // update line
                line.setEndX( x2 );
                line.setEndY( y2 );
                // draw head
                // http://www.coderanch.com/t/340443/GUI/java/Draw-arrow-head-end-line
                double dx = x2 - x1;
                double dy = y2 - y1;
                double theta = Math.atan2( dy, dx );
                double x, y, rho = theta + phi;

                x = x2 - barb * Math.cos( rho );
                y = y2 - barb * Math.sin( rho );
                head1.setStartX( x2 );
                head1.setStartY( y2 );
                head1.setEndX( x );
                head1.setEndY( y );
                rho = theta - phi;
                x = x2 - barb * Math.cos( rho );
                y = y2 - barb * Math.sin( rho );
                head2.setStartX( x2 );
                head2.setStartY( y2 );
                head2.setEndX( x );
                head2.setEndY( y );
            }
        }
    }

}
class MouseHandler实现EventHandler{
private boolean gotFirst=false;
专线,头1,头2;
专用窗格;
专用双x1,y1,x2,y2;
双φ=数学环面(40);
双倒钩=20;
公共鼠标手柄(窗格){
this.pane=窗格;
}
@凌驾
公共无效句柄(MouseeEvent事件){
如果(event.getEventType()==MouseEvent.MOUSE_单击){
如果(!gotFirst){
x1=x2=event.getX();
y1=y2=event.getY();
直线=新线(x1,y1,x2,y2);
head1=新线(x2,y2,x2,y2);
head2=新线(x2,y2,x2,y2);
pane.getChildren().add(行);
pane.getChildren().add(head1);
pane.getChildren().add(head2);
gotFirst=true;
}否则{
行=空;
gotFirst=false;
}
}否则{
如果(行!=null){
x2=event.getX();
y2=event.getY();
//更新行
行。setEndX(x2);
行。setEndY(y2);
//牵引头
// http://www.coderanch.com/t/340443/GUI/java/Draw-arrow-head-end-line
双dx=x2-x1;
双dy=y2-y1;
双θ=Math.atan2(dy,dx);
双x,y,ρ=θ+φ;
x=x2-倒钩*数学cos(rho);
y=y2-倒钩*数学sin(rho);
头1.设置起点x(x2);
标题1.设置起点(y2);
head1.setEndX(x);
头1.塞滕迪(y);
ρ=θ-φ;
x=x2-倒钩*数学cos(rho);
y=y2-倒钩*数学sin(rho);
头2.setStartX(x2);
标题2.设置起点(y2);
head2.setEndX(x);
头2.塞滕迪(y);
}
}
}
}

您可以将鼠标处理程序添加到边框窗格中,并在鼠标移动时绘制箭头。 也许有更好的方法,但这就是我想到的:

将鼠标处理程序添加到边框窗格:

MouseHandler mh = new MouseHandler( pane );
pane.setOnMouseClicked( mh );
pane.setOnMouseMoved( mh );
处理程序类可以如下所示:

class MouseHandler implements EventHandler< MouseEvent > {
    private boolean gotFirst    = false;
    private Line    line, head1, head2;
    private Pane    pane;
    private double  x1, y1, x2, y2;
    double          phi         = Math.toRadians( 40 );
    double          barb        = 20;

    public MouseHandler( Pane pane ) {
        this.pane = pane;
    }

    @Override
    public void handle( MouseEvent event ) {
        if( event.getEventType() == MouseEvent.MOUSE_CLICKED ) {
            if( !gotFirst ) {
                x1 = x2 = event.getX();
                y1 = y2 = event.getY();
                line = new Line( x1, y1, x2, y2 );
                head1 = new Line( x2, y2, x2, y2 );
                head2 = new Line( x2, y2, x2, y2 );
                pane.getChildren().add( line );
                pane.getChildren().add( head1 );
                pane.getChildren().add( head2 );
                gotFirst = true;
            } else {
                line = null;
                gotFirst = false;
            }
        } else {
            if( line != null ) {
                x2 = event.getX();
                y2 = event.getY();
                // update line
                line.setEndX( x2 );
                line.setEndY( y2 );
                // draw head
                // http://www.coderanch.com/t/340443/GUI/java/Draw-arrow-head-end-line
                double dx = x2 - x1;
                double dy = y2 - y1;
                double theta = Math.atan2( dy, dx );
                double x, y, rho = theta + phi;

                x = x2 - barb * Math.cos( rho );
                y = y2 - barb * Math.sin( rho );
                head1.setStartX( x2 );
                head1.setStartY( y2 );
                head1.setEndX( x );
                head1.setEndY( y );
                rho = theta - phi;
                x = x2 - barb * Math.cos( rho );
                y = y2 - barb * Math.sin( rho );
                head2.setStartX( x2 );
                head2.setStartY( y2 );
                head2.setEndX( x );
                head2.setEndY( y );
            }
        }
    }

}
class MouseHandler实现EventHandler{
private boolean gotFirst=false;
专线,头1,头2;
专用窗格;
专用双x1,y1,x2,y2;
双φ=数学环面(40);
双倒钩=20;
公共鼠标手柄(窗格){
this.pane=窗格;
}
@凌驾
公共无效句柄(MouseeEvent事件){
如果(event.getEventType()==MouseEvent.MOUSE_单击){
如果(!gotFirst){
x1=x2=event.getX();
y1=y2=event.getY();
直线=新线(x1,y1,x2,y2);
head1=新线(x2,y2,x2,y2);
head2=新线(x2,y2,x2,y2);
pane.getChildren().add(行);
pane.getChildren().add(head1);
pane.getChildren().add(head2);
gotFirst=true;
}否则{
行=空;