我正在尝试使用这些教程制作带箭头的连接圆和四边形:
JavaFX line/curve with arrow head,
CubicCurve JavaFX,
JavaFX: How to connect two Nodes by a Line?
我的问题:当我移动四边形时,箭头没有与四边形连接,也没有连接到圆形边缘
这是我的项目回购:https://github.com/ehnsnk/cho_ford_min_max
我在开发分支工作,这些是我的应用程序的快捷方式
CTRL +右键单击:删除圆圈,
右键单击:删除QuadCurve
CTRL +左键单击:链接两个圆圈,
shape类位于edu.emit.project.view.shape包中
并且V(xi,xj)必须遵循controlX,controlY
数据是https://github.com/ehnsnk/unnamed-proj/的exo1.ro,
谢谢
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.emit.project.view.shape;
import edu.emit.project.Main;
import edu.emit.project.controller.FordFulkersonFXController;
import edu.emit.project.model.serializable.SommetSerializable;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.StrokeType;
/**
*
* @author heniroger
*/
public class SommetFX extends Circle{
Main app;
private int id=0;
private final SommetFX context = this;
private FordFulkersonFXController controller;
private Label lblName;
private TextField txfLambda;
private Label lblLambda;
private double lambda;
private boolean deletable = false;
public static int SOMMET_TYPE_X1 =0;
public static int SOMMET_TYPE_XI =1;
public static int SOMMET_TYPE_XN =2;
private int typeSommet = SOMMET_TYPE_XI;
private ArrayList listLiens = new ArrayList();
private SommetSerializable sommetSerializable;
public SommetFX() {
super();
setFill(Color.WHITE);
setStroke(Color.BLACK.deriveColor(0, 1, 1, 0.5));
setStrokeWidth(2);
setStrokeType(StrokeType.CENTERED);
setCenterX(150);
setCenterY(150);
setRadius(30.0f);
lblName = new Label("X1");
lblLambda= new Label("\u03BB=");
txfLambda = new TextField("0");
txfLambda.setPrefWidth(50);
txfLambda.setEditable(false);
initialize();
enableDrag();
enableMouseClickToBind();
}
public void setApp(Main app){this.app = app;}
public void lier(DoubleProperty x, DoubleProperty y){
try {
if (app == null) {
throw new AppNotDefinedException();
}
} catch (Exception ex) {
Logger.getLogger(SommetFX.class.getName()).log(Level.SEVERE, null, ex);
}
bindSommetFXComponent();
x.bind(centerXProperty());
y.bind(centerYProperty());
}
public void bindSommetFXComponent(){
lblName.layoutXProperty().bind(centerXProperty());
lblName.layoutYProperty().bind(centerYProperty());
lblLambda.layoutXProperty().bind(centerXProperty());
lblLambda.layoutYProperty().bind(centerYProperty());
txfLambda.layoutXProperty().bind(centerXProperty());
txfLambda.layoutYProperty().bind(centerYProperty());
}
private void enableDrag() {
final Delta dragDelta = new Delta();
setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
// record a delta distance for the drag and drop operation.
dragDelta.x = getCenterX() - mouseEvent.getX();
dragDelta.y = getCenterY() - mouseEvent.getY();
getScene().setCursor(Cursor.MOVE);
if(mouseEvent.isControlDown() && mouseEvent.isSecondaryButtonDown()){deletable = true; }
}
});
setOnMouseReleased(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
getScene().setCursor(Cursor.HAND);
if (deletable) {
delete();
}
}
});
setOnMouseDragged(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
double newX = mouseEvent.getX() + dragDelta.x;
if (newX > 0 && newX 0 && newY () {
@Override public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
getScene().setCursor(Cursor.HAND);
setStroke(Color.BLUE);
}
}
});
setOnMouseExited(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
getScene().setCursor(Cursor.DEFAULT);
setStroke(Color.BLACK.deriveColor(0, 1, 1, 0.5));
}
}
});
}
public class AppNotDefinedException extends Exception{
public AppNotDefinedException()throws Exception{
System.err.println("App is null or not defined");
}
}
/**
* @return the lblName
*/
public Label getLblName() {
return lblName;
}
/**
* @param lblName the lblName to set
*/
public void setLblName(Label lblName) {
this.lblName = lblName;
}
/**
* @return the txfLambda
*/
public TextField getTxfLambda() {
return txfLambda;
}
/**
* @param txfLambda the txfLambda to set
*/
public void setTxfLambda(TextField txfLambda) {
this.txfLambda = txfLambda;
}
public void initialize(){
lblName.setLayoutX(getCenterX()-10);
lblName.setLayoutY(getCenterY()-10);
lblLambda.setLayoutX(getCenterX()-45);
lblLambda.setLayoutY(getCenterY()-70);
txfLambda.setLayoutX(getCenterX()-25);
txfLambda.setLayoutY(getCenterY()-75);
}
public void update(){
initialize();
}
private void enableMouseClickToBind(){
setOnMouseClicked(new EventHandler() {
@Override
public void handle(MouseEvent event) {
if (event.isControlDown()) {
if (Tetha.startSommet != null) {
if (Tetha.startSommet.equals(context)) {
Tetha.startSommet = null;
return;
}
Tetha.endSommet = context;
ArcFX lien = new ArcFX();
Pointe pointe = new Pointe();
pointe.linkTo(lien, 40.0f);
app.pointes.add(pointe);
lien.setPointe(pointe);
lien.lier(Tetha.startSommet.centerXProperty(), Tetha.startSommet.centerYProperty(), Tetha.endSommet.centerXProperty(), Tetha.endSommet.centerYProperty());
lien.setControlY(175);
lien.setController(getController());
Tetha.startSommet.getNextSommets().add(new Object[]{ Tetha.endSommet,lien});
Tetha.endSommet.getPreviewSommets().add(new Object[]{ Tetha.startSommet,lien});
Tetha.startSommet.getListNextSommets().add(Tetha.endSommet);
Tetha.endSommet.getListPreviewSommets().add(Tetha.startSommet);
Tetha.startSommet.getListLiens().add(lien);
Tetha.endSommet.getListLiens().add(lien);
lien.getListSommets().add(Tetha.startSommet);
lien.getListSommets().add(Tetha.endSommet);
lien.setV_ij(Double.parseDouble(lien.getTxfVij().getText()));
getController().getGraphManager().getArcFXList().add(lien);
Group group = (Group) context.getParent();
group.getChildren().addAll(pointe,lien,lien.getVij(),lien.getTxfVij());
pointe.update();
Tetha.startSommet =null;
Tetha.endSommet =null;
}else{
Tetha.startSommet = context;
}
}
}
});
}
/**
* @return the alreadyBounded
*/
public boolean isAlreadyBounded() {
return alreadyBounded;
}
/**
* @param alreadyBounded the alreadyBounded to set
*/
public void setAlreadyBounded(boolean alreadyBounded) {
this.alreadyBounded = alreadyBounded;
}
/**
* @return the previewSommets
*/
public ArrayList getPreviewSommets() {
return previewSommets;
}
/**
* @param previewSommets the previewSommets to set
*/
public void setPreviewSommets(ArrayList previewSommets) {
this.previewSommets = previewSommets;
}
/**
* @return the nextSommets
*/
public ArrayList getNextSommets() {
return nextSommets;
}
/**
* @param nextSommets the nextSommets to set
*/
public void setNextSommets(ArrayList nextSommets) {
this.nextSommets = nextSommets;
}
/**
* @return the listPreviewSommets
*/
public ArrayList getListPreviewSommets() {
return listPreviewSommets;
}
/**
* @return the listLiens
*/
public ArrayList getListLiens() {
return listLiens;
}
/**
* @param listLiens the listLiens to set
*/
public void setListLiens(ArrayList listLiens) {
this.listLiens = listLiens;
}
/**
* @return the typeSommet
*/
public int getTypeSommet() {
return typeSommet;
}
/**
* @param typeSommet the typeSommet to set
*/
public void setTypeSommet(int typeSommet) {
this.typeSommet = typeSommet;
}
/**
* @return the id
*/
public int getID() {
return id;
}
/**
* @param id the id to set
*/
public void setID(int id) {
this.id = id;
}
/**
* @return the lambda
*/
public double getLambda() {
return lambda;
}
/**
* @param lambda the lambda to set
*/
public void setLambda(double lambda) {
this.lambda = lambda;
}
/**
* @return the controller
*/
public FordFulkersonFXController getController() {
return controller;
}
/**
* @param controller the controller to set
*/
public void setController(FordFulkersonFXController controller) {
this.controller = controller;
}
public void deleteFromGraphManager(){
ArrayList sommetFXList = getController().getGraphManager().getSommetFXList();
for (int i = 0; i
private void enableMouseClickToBind(); method to bind 2 SommetFX(Circle)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.emit.project.view.shape;
import edu.emit.project.controller.FordFulkersonFXController;
import edu.emit.project.model.serializable.ArcSerializable;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.QuadCurve;
import javafx.scene.shape.StrokeLineCap;
/**
*
* @author heniroger
*/
public class ArcFX extends QuadCurve{
private final ArcFX context = this;
private FordFulkersonFXController controller;
private Label vij = new Label("V(xi,xj)=");
private TextField txfVij = new TextField("0");
private double v_ij;
private Pointe pointe;
private ArrayList listSommets = new ArrayList();
private boolean up =true;
private boolean deletable = false;
private ArcSerializable arcSerializable;
public ArcFX(){
setStrokeWidth(2);
setFill(Color.WHITE.deriveColor(1, 1, 1, 0));
setStroke(Color.BLACK.deriveColor(0, 1, 1, 0.5));
setStrokeLineCap(StrokeLineCap.BUTT);
// getStrokeDashArray().setAll(10.0,5.);
setMouseTransparent(false);
vij.setLayoutX(getControlX()-75);
vij.setLayoutY(getControlY()+75);
txfVij.setPrefWidth(50);
txfVij.setLayoutX(getControlX()-75);
txfVij.setLayoutY(getControlY()+75);
}
public void lier(DoubleProperty startX,DoubleProperty startY,DoubleProperty endX,DoubleProperty endY){
try {
if (pointe == null) {
throw new PointeClassNotSetException();
}
} catch (PointeClassNotSetException e) {
Logger.getLogger(ArcFX.class.getName()).log(Level.SEVERE, null, e);
return;
}
startXProperty().bind(startX);
startYProperty().bind(startY);
endXProperty().bind(endX);
endYProperty().bind(endY);
// controlXProperty().bind(startX.add(endX));
//controlXProperty().bind(startY.add(endY));
getVij().layoutXProperty().bind(controlXProperty().add(75));
getVij().layoutYProperty().bind(controlYProperty().subtract(25));
getTxfVij().layoutXProperty().bind(controlXProperty().add(135));
getTxfVij().layoutYProperty().bind(controlYProperty().subtract(30));
enableClickEvent();
enableDrag();
}
public class PointeClassNotSetException extends Exception{
public PointeClassNotSetException(){
System.err.println("Pointe Object is not set");
}
}
/**
* @return the pointe
*/
public Pointe getPointe() {
return pointe;
}
/**
* @param pointe the pointe to set
*/
public void setPointe(Pointe pointe) {
this.pointe = pointe;
}
private void enableClickEvent(){
setOnMouseClicked(new EventHandler() {
@Override
public void handle(MouseEvent event) {
}
});
}
private void enableDrag(){
final Delta dragDelta = new Delta();
setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
// record a delta distance for the drag and drop operation.
dragDelta.x = getControlX() - mouseEvent.getX();
dragDelta.y = getControlY()- mouseEvent.getY();
getScene().setCursor(Cursor.MOVE);
if (mouseEvent.isSecondaryButtonDown()) { deletable = true; }
}
});
setOnMouseReleased(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
getScene().setCursor(Cursor.HAND);
if (deletable) {
delete();
}
}
});
setOnMouseDragged(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
if (mouseEvent.isPrimaryButtonDown()) {
double newX = mouseEvent.getX() + dragDelta.x;
if (newX > 0 && newX 0 && newY () {
@Override public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
getScene().setCursor(Cursor.HAND);
setStroke(Color.GREEN);
}
}
});
setOnMouseExited(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
getScene().setCursor(Cursor.DEFAULT);
setStroke(Color.BLACK.deriveColor(0, 1, 1, 0.5));
}
}
});
}
/**
* @return the up
*/
public boolean isUp() {
return up;
}
/**
* @param up the up to set
*/
public void setUp(boolean up) {
this.up = up;
}
/**
* @return the listSommets
*/
public ArrayList getListSommets() {
return listSommets;
}
/**
* @param listSommets the listSommets to set
*/
public void setListSommets(ArrayList listSommets) {
this.listSommets = listSommets;
}
public void delete(){
setStroke(Color.BLACK);
deleteFromGraphManager();
Group group = (Group) context.getParent();
if (context.getVij() == null) {
return;
}
group.getChildren().remove(context.getVij());
group.getChildren().remove(context.getTxfVij());
group.getChildren().remove(context.getPointe());
group.getChildren().remove(context);
}
/**
* @return the vij
*/
public Label getVij() {
return vij;
}
/**
* @param vij the vij to set
*/
public void setVij(Label vij) {
this.vij = vij;
}
/**
* @return the v_ij
*/
public double getV_ij() {
return v_ij;
}
/**
* @param v_ij the v_ij to set
*/
public void setV_ij(double v_ij) {
this.v_ij = v_ij;
}
/**
* @return the arcSerializable
*/
public ArcSerializable getArcSerializable() {
return arcSerializable;
}
/**
* @param arcSerializable the arcSerializable to set
*/
public void setArcSerializable(ArcSerializable arcSerializable) {
this.arcSerializable = arcSerializable;
}
/**
* @return the controller
*/
public FordFulkersonFXController getController() {
return controller;
}
/**
* @param controller the controller to set
*/
public void setController(FordFulkersonFXController controller) {
this.controller = controller;
}
public void deleteFromGraphManager(){
ArrayList arcFXList = getController().getGraphManager().getArcFXList();
for (int i = 0; i "+this.getListSommets().get(1).getID();
return str;
}
}
public void lier(DoubleProperty startX,DoubleProperty startY,DoubleProperty endX,DoubleProperty endY); bind coordinate of circle to quadcurve.
My problem is on private void enableDrag(); method i can't handle arrow(Pointe) to follow quadCurve(ArcFX). This method is the same as in the tutorial and i just modify a few lines.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.emit.project.view.shape;
import edu.emit.project.controller.FordFulkersonFXController;
import edu.emit.project.model.serializable.ArcSerializable;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.QuadCurve;
import javafx.scene.shape.StrokeLineCap;
/**
*
* @author heniroger
*/
public class ArcFX extends QuadCurve{
private final ArcFX context = this;
private FordFulkersonFXController controller;
private Label vij = new Label("V(xi,xj)=");
private TextField txfVij = new TextField("0");
private double v_ij;
private Pointe pointe;
private ArrayList listSommets = new ArrayList();
private boolean up =true;
private boolean deletable = false;
private ArcSerializable arcSerializable;
public ArcFX(){
setStrokeWidth(2);
setFill(Color.WHITE.deriveColor(1, 1, 1, 0));
setStroke(Color.BLACK.deriveColor(0, 1, 1, 0.5));
setStrokeLineCap(StrokeLineCap.BUTT);
// getStrokeDashArray().setAll(10.0,5.);
setMouseTransparent(false);
vij.setLayoutX(getControlX()-75);
vij.setLayoutY(getControlY()+75);
txfVij.setPrefWidth(50);
txfVij.setLayoutX(getControlX()-75);
txfVij.setLayoutY(getControlY()+75);
}
public void lier(DoubleProperty startX,DoubleProperty startY,DoubleProperty endX,DoubleProperty endY){
try {
if (pointe == null) {
throw new PointeClassNotSetException();
}
} catch (PointeClassNotSetException e) {
Logger.getLogger(ArcFX.class.getName()).log(Level.SEVERE, null, e);
return;
}
startXProperty().bind(startX);
startYProperty().bind(startY);
endXProperty().bind(endX);
endYProperty().bind(endY);
// controlXProperty().bind(startX.add(endX));
//controlXProperty().bind(startY.add(endY));
getVij().layoutXProperty().bind(controlXProperty().add(75));
getVij().layoutYProperty().bind(controlYProperty().subtract(25));
getTxfVij().layoutXProperty().bind(controlXProperty().add(135));
getTxfVij().layoutYProperty().bind(controlYProperty().subtract(30));
enableClickEvent();
enableDrag();
}
public class PointeClassNotSetException extends Exception{
public PointeClassNotSetException(){
System.err.println("Pointe Object is not set");
}
}
/**
* @return the pointe
*/
public Pointe getPointe() {
return pointe;
}
/**
* @param pointe the pointe to set
*/
public void setPointe(Pointe pointe) {
this.pointe = pointe;
}
private void enableClickEvent(){
setOnMouseClicked(new EventHandler() {
@Override
public void handle(MouseEvent event) {
}
});
}
private void enableDrag(){
final Delta dragDelta = new Delta();
setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
// record a delta distance for the drag and drop operation.
dragDelta.x = getControlX() - mouseEvent.getX();
dragDelta.y = getControlY()- mouseEvent.getY();
getScene().setCursor(Cursor.MOVE);
if (mouseEvent.isSecondaryButtonDown()) { deletable = true; }
}
});
setOnMouseReleased(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
getScene().setCursor(Cursor.HAND);
if (deletable) {
delete();
}
}
});
setOnMouseDragged(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
if (mouseEvent.isPrimaryButtonDown()) {
double newX = mouseEvent.getX() + dragDelta.x;
if (newX > 0 && newX 0 && newY () {
@Override public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
getScene().setCursor(Cursor.HAND);
setStroke(Color.GREEN);
}
}
});
setOnMouseExited(new EventHandler() {
@Override public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.isPrimaryButtonDown()) {
getScene().setCursor(Cursor.DEFAULT);
setStroke(Color.BLACK.deriveColor(0, 1, 1, 0.5));
}
}
});
}
/**
* @return the up
*/
public boolean isUp() {
return up;
}
/**
* @param up the up to set
*/
public void setUp(boolean up) {
this.up = up;
}
/**
* @return the listSommets
*/
public ArrayList getListSommets() {
return listSommets;
}
/**
* @param listSommets the listSommets to set
*/
public void setListSommets(ArrayList listSommets) {
this.listSommets = listSommets;
}
public void delete(){
setStroke(Color.BLACK);
deleteFromGraphManager();
Group group = (Group) context.getParent();
if (context.getVij() == null) {
return;
}
group.getChildren().remove(context.getVij());
group.getChildren().remove(context.getTxfVij());
group.getChildren().remove(context.getPointe());
group.getChildren().remove(context);
}
/**
* @return the vij
*/
public Label getVij() {
return vij;
}
/**
* @param vij the vij to set
*/
public void setVij(Label vij) {
this.vij = vij;
}
/**
* @return the v_ij
*/
public double getV_ij() {
return v_ij;
}
/**
* @param v_ij the v_ij to set
*/
public void setV_ij(double v_ij) {
this.v_ij = v_ij;
}
/**
* @return the arcSerializable
*/
public ArcSerializable getArcSerializable() {
return arcSerializable;
}
/**
* @param arcSerializable the arcSerializable to set
*/
public void setArcSerializable(ArcSerializable arcSerializable) {
this.arcSerializable = arcSerializable;
}
/**
* @return the controller
*/
public FordFulkersonFXController getController() {
return controller;
}
/**
* @param controller the controller to set
*/
public void setController(FordFulkersonFXController controller) {
this.controller = controller;
}
public void deleteFromGraphManager(){
ArrayList arcFXList = getController().getGraphManager().getArcFXList();
for (int i = 0; i "+this.getListSommets().get(1).getID();
return str;
}
}