I have a toggle buttons group with 4 different pointers

When I select the crosshair button ( right most one ) I have as follow

Each button calls a different line pointer follower :
- left most one button: it is a simple pointer without line;
- second display only vertical line pointer movement linked;
- third one only horizontal line pointer movement linked;
- a crosshair.
I would like to create a generic class to set the selected line so I can call it in the draw routine.
This generic/abstract class “will contains” the specific line pointer follower code when the appropriate button is selected, in this way the draw routine will only refer to the generic class to plot the select pointer line follower.
The code with crosshair is:
public class JavaFXApplicationMove extends Application {
Path path;
BorderPane pane;
Rectangle rect;
Line LH;
Line LV;
XYChart.Series series1 = new XYChart.Series();
SimpleDoubleProperty rectinitX = new SimpleDoubleProperty();
SimpleDoubleProperty rectinitY = new SimpleDoubleProperty();
SimpleDoubleProperty rectX = new SimpleDoubleProperty();
SimpleDoubleProperty rectY = new SimpleDoubleProperty();
@Override
public void start(Stage stage) {
stage.setTitle("Lines plot");
final NumberAxis xAxis = new NumberAxis(1, 12, 1);
final NumberAxis yAxis = new NumberAxis(0.53000, 0.53910, 0.0005);
xAxis.setAnimated(false);
yAxis.setAnimated(false);
yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
@Override
public String toString(Number object) {
return String.format("%7.5f", object);
}
});
//final LineChart<String, Number> lineChart = new LineChart<String, Number> (xAxis, yAxis);
final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);
lineChart.setCreateSymbols(false);
lineChart.setAlternativeRowFillVisible(false);
lineChart.setAnimated(true);
series1.setName("Stock1");
series1.getData().add(new XYChart.Data(1, 0.53185));
series1.getData().add(new XYChart.Data(2, 0.532235));
series1.getData().add(new XYChart.Data(3, 0.53234));
series1.getData().add(new XYChart.Data(4, 0.538765));
series1.getData().add(new XYChart.Data(5, 0.53442));
series1.getData().add(new XYChart.Data(6, 0.534658));
series1.getData().add(new XYChart.Data(7, 0.53023));
series1.getData().add(new XYChart.Data(8, 0.53001));
series1.getData().add(new XYChart.Data(9, 0.53589));
series1.getData().add(new XYChart.Data(10, 0.53476));
pane = new BorderPane();
pane.setCenter(lineChart);
Scene scene = new Scene(pane, 800, 600);
lineChart.getData().addAll(series1);
stage.setScene(scene);
path = new Path();
path.setStrokeWidth(5);
path.setStroke(Color.RED);
scene.setOnMouseClicked(mouseHandler);
scene.setOnMouseDragged(mouseHandler);
scene.setOnMouseEntered(mouseHandler);
scene.setOnMouseExited(mouseHandler);
scene.setOnMouseMoved(mouseHandler);
scene.setOnMousePressed(mouseHandler);
scene.setOnMouseReleased(mouseHandler);
rect = new Rectangle();
rect.setFill(Color.web("yellow", 0.3));
rect.setStroke(Color.MAGENTA);
rect.setStrokeDashOffset(50);
rect.widthProperty().bind(rectX.subtract(rectinitX));
rect.heightProperty().bind(rectY.subtract(rectinitY));
pane.getChildren().add(rect);
//LH=new Line();
LH=LineBuilder.create()
.startX(0)
.startY(0)
.endX(10)
.endY(.535)
.strokeWidth(1)
.stroke(Color.BLACK)
.build();
pane.getChildren().add(LH);
LV=LineBuilder.create()
.startX(0)
.startY(0)
.endX(10)
.endY(.535)
.strokeWidth(1)
.stroke(Color.BLACK)
.build();
pane.getChildren().add(LV);
stage.show();
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) {
rect.setX(mouseEvent.getX());
rect.setY(mouseEvent.getY());
rectinitX.set(mouseEvent.getX());
rectinitY.set(mouseEvent.getY());
LH.setStartX(0);
LH.setStartY(0);
LH.setEndX(0);
LH.setEndY(0);
LV.setStartX(0);
LV.setStartY(0);
LV.setEndX(0);
LV.setEndY(0);
} else if (mouseEvent.getEventType() == MouseEvent.MOUSE_RELEASED) {
rectX.set(mouseEvent.getX());
rectY.set(mouseEvent.getY());
// Hide the rectangle
rectX.set(0);
rectY.set(0);
} else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED || mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED) {
LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane.getCenter();
NumberAxis yAxis = (NumberAxis) lineChart.getYAxis();
NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();
System.out.println("(a) xAxis.getLowerBound() "+xAxis.getLowerBound()+" "+xAxis.getUpperBound());
double Tgap = xAxis.getWidth()/(xAxis.getUpperBound() - xAxis.getLowerBound());
double newXlower=xAxis.getLowerBound(), newXupper=xAxis.getUpperBound();
double newYlower=yAxis.getLowerBound(), newYupper=yAxis.getUpperBound();
double xAxisShift = getSceneShift(xAxis);
double yAxisShift = getSceneShift(yAxis);
double yAxisStep=yAxis.getHeight()/(yAxis.getUpperBound()-yAxis.getLowerBound());
double CurrentPrice=yAxis.getUpperBound()-((mouseEvent.getY()-yAxisShift)/yAxisStep);
double Delta=0.3;
if(mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED){
if(rectinitX.get() < mouseEvent.getX()){
newXlower=xAxis.getLowerBound()-Delta;
newXupper=xAxis.getUpperBound()-Delta;
}
else if(rectinitX.get() > mouseEvent.getX()){
newXlower=xAxis.getLowerBound()+Delta;
newXupper=xAxis.getUpperBound()+Delta;
}
xAxis.setLowerBound( newXlower );
xAxis.setUpperBound( newXupper );
if(rectinitY.get() < mouseEvent.getY()){
newYlower=yAxis.getLowerBound()+Delta/1000;
newYupper=yAxis.getUpperBound()+Delta/1000;
}
else if(rectinitY.get() > mouseEvent.getY()){
newYlower=yAxis.getLowerBound()-Delta/1000;
newYupper=yAxis.getUpperBound()-Delta/1000;
}
yAxis.setLowerBound(newYlower);
yAxis.setUpperBound(newYupper);
}
//System.out.println("(b) xAxis.getLowerBound() "+xAxis.getLowerBound()+" "+xAxis.getUpperBound());
rectinitX.set(mouseEvent.getX());
rectinitY.set(mouseEvent.getY());
if(mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED && mouseEvent.getY()>yAxisShift && mouseEvent.getY()<yAxisShift+yAxis.getHeight() && mouseEvent.getX()>xAxisShift && mouseEvent.getX()<xAxisShift+xAxis.getWidth()){
LH.setStartX(xAxisShift);
LH.setStartY(mouseEvent.getY());
LH.setEndX(xAxisShift+xAxis.getWidth());
LH.setEndY(mouseEvent.getY());
LV.setStartX(mouseEvent.getX());
LV.setStartY(yAxisShift);
LV.setEndX(mouseEvent.getX());
LV.setEndY(yAxisShift+yAxis.getHeight());
double XX=((mouseEvent.getX() - xAxisShift) / Tgap) + xAxis.getLowerBound();
double YY=CurrentPrice;
series1.setName(String.format("%.2g%n",XX) + ", " + String.format("%.4g%n",YY));
int XLB=(int) xAxis.getLowerBound();
int XUB=(int) xAxis.getUpperBound();
}
}
}
};
private static double getSceneShift(Node node) {
double shift = 0;
do {
shift += node.getLayoutX();
node = node.getParent();
} while (node != null);
return shift;
}
private static String getHIstLOstY(XYChart.Series S,int XLowerBound,int XUpperBound) {
double ValLOst=1000000;
double ValHIst=-1000000;
for(int i=XLowerBound; i<XUpperBound; i++){
double P=GetPrice(S,i);
if(ValHIst<P){
ValHIst=P;
}
if(ValLOst>P){
ValLOst=P;
}
}
return Double.toString(ValLOst) + "," + Double.toString(ValHIst);
}
private static double GetPrice(XYChart.Series S,int IX) {
Object SVal=S.getData().get(IX);
//return SVal.toString().toLowerCase();
String Temp=SVal.toString().replaceAll("Data", "");
Temp=Temp.replace("[", "");
Temp=Temp.replace("]", "");
String[] TempArray=Temp.split(",");
return Double.parseDouble(TempArray[1]);
}
public static void main(String[] args) {
launch(args);
}
}
All your drawing routing in handed in
EventHandler<MouseEvent>. So easiest way to change crosshair type would be substituting various handlers.By going a bit deeper you’ll see that every crosshair drawing is based on similar parameters and can be divided in 3 steps: start, update and end.
From what I see in your code important parameters are
sceneShiftX, sceneShiftY, mouseX, mouseY. So, you need to refactor out drawing code from mouse event handler to a separate class with next methods:You put crosshair related code from
MouseEvent.MOUSE_PRESSEDblock tostart(), fromMouseEvent.MOUSE_RELEASEDto finish() and fromMouseEvent.MOUSE_DRAGGEDtoupdate().Now as you separated all your drawing data from mouse events and can introduce an
interface Crosshairwhich will look similar to class above and makeSimpleCrosshair implement Crosshair.The rest is easy. Create classes implementing
Crosshairwhich will do drawing for other crosshair type and introduce fieldprivate Crosshair currentCrosshair;which you can update with concrete implementation on toolbar button click.And your mouse events handler will look like (aside from zoom logic):