尝试制作圆图软件。 使用鼠标拖动事件更改圆形组件。
遇到两个问题:
1) - 调用了s的中心XProperty侦听器但是它的X坐标没有改变,怎么回事?
2) - 我在updateComponents()中给出了相同的参数,但是一旦我打印出关于圆圈的描述,控制台中就会出现为centerXProperty监听器反转参数的情况。
此处代码和控制台打印以获取更多详细信息:
public class TDGAPIUI extends Application {
@Override
public void start(Stage primaryStage) throws NoSommet2DException, RelationMismatchException {
Sommet sommetA = new Sommet("A");
Sommet sommetB = new Sommet("B");
ArcPondere e1 = new ArcPondere("e1", 5, sommetA, sommetB);
Sommet2D sommet2DA = new Sommet2D(sommetA);
Sommet2D sommet2DB = new Sommet2D(sommetB);
Relation2D relation2De1 = new Relation2D(e1);
StackPane root = new StackPane();
root.setStyle("-fx-background-color: white;");
root.getChildren().addAll(relation2De1);
root.getChildren().addAll(sommet2DA,sommet2DB);
Scene scene = new Scene(root, 800, 600);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
public class Sommet implements Comparable{
private SimpleObjectProperty<ArrayList<Relation>> listeRelations = new SimpleObjectProperty<ArrayList<Relation>>(new ArrayList<Relation>());
private SimpleObjectProperty<Sommet2D> sommet2D = new SimpleObjectProperty<Sommet2D>(null);
private SimpleStringProperty label = new SimpleStringProperty("No Label");
public Sommet(String label){
this.label.set(label);
}
public Sommet(String label,Relation ... relations){
this.label.set(label);
this.listeRelations.getValue().addAll(Arrays.asList(relations));
}
public SimpleStringProperty labelProperty(){
return this.label;
}
public SimpleObjectProperty<ArrayList<Relation>> listeRelationsProperty(){
return this.listeRelations;
}
public SimpleObjectProperty<Sommet2D> sommet2DProperty(){
return this.sommet2D;
}
/**
* @return the label
*/
public String getLabel() {
return label.getValue();
}
/**
* @param label the label to set
*/
public void setLabel(String label) {
this.label.setValue(label);
}
/**
* @return the listeRelations
*/
public ArrayList<Relation> getListeRelations() {
return listeRelations.getValue();
}
/**
* @param listeRelations the listeRelations to set
*/
public void setListeRelations(ArrayList<Relation> listeRelations) {
this.listeRelations.setValue(listeRelations);
}
public Sommet2D getSommet2D(){
return this.sommet2D.get();
}
public void setSommet2D(Sommet2D sommet2D){
this.sommet2D.setValue(sommet2D);
}
@Override
public String toString(){
return "Description du Sommet: " + this.label.getValue() + "\n";
}
@Override
public boolean equals(Object o){
if(o instanceof Sommet)
return this.label.getValue().equals(((Sommet) o).getLabel());
return false;
}
@Override
public int compareTo(Object o) {
if(o instanceof Sommet)
return this.label.getValue().compareTo(((Sommet) o).label.getValue());
return 0;
}
public boolean isIncidentTo(Relation relation){
for(Relation r: this.listeRelations.getValue())
if(relation.equals(r)) return true;
return false;
}
}
public class ArcPondere extends Arc {
public ArcPondere(String label, double poid, Sommet sommetGauche, Sommet sommetDroit) {
super(label, sommetGauche, sommetDroit);
this.ponderationValue.setValue(new ValuePonderation(poid));
}
/**
* @return the poid
*/
public double getPoid() {
return this.ponderationValue.getValue().getPoid();
}
/**
* @param poid the poid to set
*/
public void setPoid(double poid) {
this.ponderationValue.getValue().setPoid(poid);
}
public SimpleDoubleProperty poidProperty(){
return this.ponderationValue.getValue().poidProperty();
}
@Override
public boolean equals(Object o){
if(o instanceof ArcPondere)
return super.equals(o) && this.ponderationValue.getValue().getPoid() == ((ArcPondere) o).ponderationValue
.getValue().getPoid();
return false;
}
@Override
public int compareTo(Object o){
if(o instanceof ArcPondere)
return (int)(this.getPoid() - ((ArcPondere) o).getPoid());
return 0;
}
}
public class Sommet2D extends Circle {
private SimpleObjectProperty<Sommet> sommet = new SimpleObjectProperty<Sommet>(null);
private Text label = new Text();
public Sommet2D(Sommet sommet){
this.sommet.setValue(sommet);
this.sommet.getValue().setSommet2D(this);
this.initGraphicSettings(
"-fx-fill: rgb(255,255,255); "
+ "-fx-stroke-width: 2px; "
+ "-fx-stroke: rgba(0,0,0,1);",
"-fx-fill: rgb(0,0,0);");
this.setRadius(25.0);
this.setCenterX(Screen.getMainScreen().getWidth()/2);
this.setCenterY(Screen.getMainScreen().getHeight()/2);
this.layoutXProperty().addListener((observable) -> { this.setLayoutX(0.0); });
this.layoutYProperty().addListener((observable) -> { this.setLayoutY(0.0); });
this.label.textProperty().bind(sommet.labelProperty());
this.label.layoutXProperty().addListener((observable) -> { this.label.setLayoutX(0.0); });
this.label.layoutYProperty().addListener((observable) -> { this.label.setLayoutY(0.0); });
this.label.xProperty().bind(this.centerXProperty().subtract(this.label.prefWidth(0) / 2));
this.label.yProperty().bind(this.centerYProperty().add(this.label.prefHeight(0)/4));
this.setOnMouseDragged(new EventHandler<MouseEvent>(){
@Override
public void handle(MouseEvent event) {
double xPos = event.getSceneX();
double yPos = event.getSceneY();
setCenterX(xPos);
setCenterY(yPos);
}
});
this.parentProperty().addListener(new ChangeListener<Parent>(){
@Override
public void changed(ObservableValue<? extends Parent> observable, Parent oldValue, Parent newValue) {
if(newValue != null){
if(label.getParent() != null)
(((Pane)label.getParent()).getChildren()).remove(label);
(((Pane)newValue).getChildren()).add(label);
}
}
});
}
public void setSommet(Sommet sommet){
this.sommet.setValue(sommet);
}
public Sommet getSommet(){
return this.sommet.getValue();
}
public void initGraphicSettings(String circleCss,String labelCss){
this.label.setStyle(labelCss);
this.setStyle(circleCss);
}
}
public class Relation2D extends Line{
private SimpleObjectProperty<Relation> relation = new SimpleObjectProperty<Relation>(null);
private Line[] arrows = new Line[2];
private Text label = new Text();
public Relation2D(Relation relation) throws NoSommet2DException {
Sommet2D sg = relation.getSommetGauche().getSommet2D();
Sommet2D sd = relation.getSommetDroit().getSommet2D();
if(sd == null || sg == null)
throw new NoSommet2DException();
this.relation.setValue(relation);
this.initLabelBindings();
this.initComponentsBindings();
this.initParentBindings();
this.initGraphicSettings("-fx-fill: rgb(255,255,255); -fx-stroke-width: 5px; -fx-stroke: rgba(0,0,0,1);",
"-fx-fill: rgb(0,0,0);");
if(relation instanceof Arc)
this.initArrows();
}
public void setSommet(Relation relation){
this.relation.setValue(relation);
}
public Relation getRelation(){
return this.relation.getValue();
}
public void initGraphicSettings(String lineCss,String labelCss){
this.setStyle(labelCss);
this.label.setStyle(labelCss);
}
private void initLabelBindings(){
this.label.setX(Double.MIN_VALUE);
this.label.setY(Double.MIN_VALUE);
Relation relation = this.getRelation();
this.label.textProperty().bind(relation.labelProperty().concat(
(relation instanceof AretePondere ? ": " + ((AretePondere) relation).getPoid() : (
relation instanceof ArcPondere ? ": " + ((ArcPondere) relation).getPoid() : ""))));
this.label.layoutXProperty().addListener(event -> this.setLayoutX(0.0));
this.label.layoutYProperty().addListener(event -> this.setLayoutY(0.0));
this.label.layoutXProperty().addListener(event -> this.label.setLayoutX(0.0));
this.label.layoutYProperty().addListener(event -> this.label.setLayoutY(0.0));
this.label.xProperty().bind((this.startXProperty().add((this.endXProperty().subtract(this.startXProperty())).divide(2))).subtract(this.label.getText().length() * 7/2 * this.label.getStrokeWidth()));
this.label.yProperty().bind((this.startYProperty().add((this.endYProperty().subtract(this.startYProperty())).divide(2))).subtract(this.label.getText().length() * this.label.getStrokeWidth()));
}
private void initComponentsBindings(){
// Layout ne doit pas influencer les composantes des vecteurs
this.layoutXProperty().addListener(event -> this.setLayoutX(0.0));
this.layoutYProperty().addListener(event -> this.setLayoutY(0.0));
//
this.setStartX(Double.MIN_VALUE);
this.setEndX(Double.MAX_VALUE);
this.setStartY(Double.MIN_VALUE);
this.setEndY(Double.MAX_VALUE);
Sommet2D sg = this.getRelation().getSommetGauche().getSommet2D();
Sommet2D sd = this.getRelation().getSommetDroit().getSommet2D();
DoubleBinding dx = sd.centerXProperty().subtract(sg.centerXProperty());
DoubleBinding dy = sd.centerYProperty().subtract(sg.centerYProperty());
sg.centerXProperty().addListener((observable) -> {
System.out.println("SG X Event:");
updateComponents(dx.getValue(),dy.getValue(),sg,sd);
//updateArrowsComponents(dx.getValue(),dy.getValue());
System.out.println("---------------------------------------------");
});
sg.centerYProperty().addListener((value) -> {
System.out.println("SG Y Event:");
updateComponents(dx.getValue(),dy.getValue(),sg,sd);
//updateArrowsComponents(dx.getValue(),dy.getValue());
System.out.println("---------------------------------------------");
});
sd.centerXProperty().addListener((observable) -> {
System.out.println("SD X Event:");
updateComponents(dx.getValue(),dy.getValue(),sg,sd);
//updateArrowsComponents(dx.getValue(),dy.getValue());
System.out.println("---------------------------------------------");
});
sd.centerYProperty().addListener((observable) -> {
System.out.println("SD Y Event:");
updateComponents(dx.getValue(),dy.getValue(),sg,sd);
//updateArrowsComponents(dx.getValue(),dy.getValue());
System.out.println("---------------------------------------------");
});
}
private void initParentBindings(){
this.parentProperty().addListener(new ChangeListener<Parent>(){
@Override
public void changed(ObservableValue<? extends Parent> observable, Parent oldValue, Parent newValue) {
if(newValue != null){
if(label.getParent() != null)
(((Pane)label.getParent()).getChildren()).removeAll(label);
(((Pane)newValue).getChildren()).addAll(label);
}
}
});
}
private synchronized void updateComponents(double dx, double dy, Sommet2D sg, Sommet2D sd){
double x1 = sg.getCenterX();
double y1 = sg.getCenterY();
double x2 = sd.getCenterX();
double y2 = sd.getCenterY();
System.out.println("SG: " + sg);
System.out.println("SD: " + sd);
double newModule = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
double cosAlpha = (x2 - x1) / newModule;
double alpha = Math.acos(cosAlpha);
double sinAlpha = Math.sin(alpha);
double r1x = cosAlpha * sg.getRadius();
double r1y = sinAlpha * Math.signum(dy) * sg.getRadius();
double r2x = cosAlpha * sd.getRadius();
double r2y = sinAlpha * Math.signum(dy) * sd.getRadius();
this.setStartX(x1 + r1x);
this.setStartY(y1 + r1y);
this.setEndX(x2 - r2x);
this.setEndY(y2 - r2y);
}
private synchronized void initArrows(){
this.arrows[0] = new Line();
this.arrows[1] = new Line();
this.arrows[0].layoutXProperty().addListener(event -> this.arrows[0].setLayoutX(0.0));
this.arrows[0].layoutYProperty().addListener(event -> this.arrows[0].setLayoutY(0.0));
this.arrows[1].layoutXProperty().addListener(event -> this.arrows[1].setLayoutX(0.0));
this.arrows[1].layoutYProperty().addListener(event -> this.arrows[1].setLayoutY(0.0));
this.arrows[0].setStroke(Paint.valueOf("#FF0000"));
this.arrows[1].setStroke(Paint.valueOf("#0000FF"));
this.parentProperty().addListener(new ChangeListener<Parent>(){
@Override
public void changed(ObservableValue<? extends Parent> observable, Parent oldValue, Parent newValue) {
if(newValue != null){
if(arrows[0].getParent() != null)
(((Pane)arrows[0].getParent()).getChildren()).removeAll(arrows[0]);
if(arrows[1].getParent() != null)
(((Pane)arrows[1].getParent()).getChildren()).removeAll(arrows[1]);
(((Pane)newValue).getChildren()).addAll(arrows[0]);
(((Pane)newValue).getChildren()).addAll(arrows[1]);
}
}
});
}
private synchronized void updateArrowsComponents(double dx, double dy){
this.arrows[0].setEndX(this.getEndX());
this.arrows[0].setEndY(this.getEndY());
this.arrows[1].setEndX(this.getEndX());
this.arrows[1].setEndY(this.getEndY());
final double h = 0.5;
final double d = 25;
double[] lineVector = new double[]{
1, (this.getEndY() - this.getStartY()) / (this.getEndX() - this.getStartX())
};
double[] wVector = new double[]{
- Math.signum(dy) * lineVector[1] * h / Math.sqrt(lineVector[1] * lineVector[1] + 1),
Math.signum(dy) * h / Math.sqrt(lineVector[1] * lineVector[1] + 1),
};
double[] wPrVector = new double[]{
-wVector[0], -wVector[1]
};
double[] uwVector = new double[]{
wVector[0] - lineVector[0],
wVector[1] - lineVector[1]
};
double[] uwPrVector = new double[]{
wPrVector[0] - lineVector[0],
wPrVector[1] - lineVector[1]
};
//System.out.println("wVector: " + Arrays.toString(wVector));
//System.out.println("wPrVector: " + Arrays.toString(wPrVector));
//System.out.println("EndX: " + this.getEndX());
double Xp = this.getEndX() - d * Math.signum(dx) * Math.cos(Math.atan(h/d));
double Yp = lineVector[1] * Xp + (this.getEndY() - lineVector[1] * Xp);
//System.out.println("P(X,Y) = (" + Xp + "," + Yp + ")");
double Xw = (this.getEndY() - Yp + (wVector[1]/wVector[0]) * Xp - (uwVector[1]/uwVector[0]) * this.getEndX()) / (
(wVector[1]/wVector[0]) - (uwVector[1]/uwVector[0]));
double XwPr = (this.getEndY() - Yp + (wPrVector[1]/wPrVector[0]) * Xp - (uwPrVector[1]/uwPrVector[0]) * this.getEndX()) / (
(wPrVector[1]/wPrVector[0]) - (uwPrVector[1]/uwPrVector[0]));
double Yw = (wVector[1]/wVector[0]) * Xw + Yp - (wVector[1]/wVector[0]) * Xp;
double YwPr = (wPrVector[1]/wPrVector[0]) * XwPr + Yp - (wPrVector[1]/wPrVector[0]) * Xp;
this.arrows[0].setStartX(Xw);
this.arrows[0].setStartY(Yw);
this.arrows[1].setStartX(XwPr);
this.arrows[1].setStartY(YwPr);
}
}
public abstract class Relation implements Comparable {
private SimpleStringProperty label = new SimpleStringProperty("No Label");
private SimpleObjectProperty<Sommet> sommetGauche = new SimpleObjectProperty<Sommet>(null),
sommetDroit = new SimpleObjectProperty<Sommet>(null);
private SimpleObjectProperty<Relation2D> relation2D = new SimpleObjectProperty<Relation2D>(null);
protected SimpleObjectProperty<ComportementPonderation> ponderationValue = new SimpleObjectProperty<ComportementPonderation>(
new NoPonderation());
public Relation(String label, Sommet sommetGauche, Sommet sommetDroit){
this.label.set(label);
this.sommetGauche.setValue(sommetGauche);
this.sommetDroit.setValue(sommetDroit);
this.sommetDroit.getValue().getListeRelations().add(this);
this.sommetGauche.getValue().getListeRelations().add(this);
}
/**
* @return the label
*/
public String getLabel() {
return label.getValue();
}
/**
* @param label the label to set
*/
public void setLabel(String label) {
this.label.setValue(label);
}
/**
* @return the sommetGauche
*/
public Sommet getSommetGauche() {
return sommetGauche.getValue();
}
/**
* @param sommetGauche the sommetGauche to set
*/
public void setSommetGauche(Sommet sommetGauche) {
this.sommetGauche.setValue(sommetGauche);
}
/**
* @return the sommetDroit
*/
public Sommet getSommetDroit() {
return sommetDroit.getValue();
}
/**
* @param sommetDroit the sommetDroit to set
*/
public void setSommetDroit(Sommet sommetDroit) {
this.sommetDroit.setValue(sommetDroit);
}
public void setRelation2D(Relation2D relation2D){
this.relation2D.setValue(relation2D);
}
public Relation2D getRelation2D(){
return this.relation2D.getValue();
}
@Override
public int compareTo(Object o) {
return (int)(this.label.getValue().compareTo(((Relation)o).getLabel()));
}
@Override
public boolean equals(Object o){
if(o instanceof Relation)
return this.label.getValue().equals(((Relation) o).getLabel());
return false;
}
public SimpleObjectProperty<Sommet> sommetGaucheProperty(){
return this.sommetGauche;
}
public SimpleObjectProperty<Sommet> sommetDroitProperty(){
return this.sommetDroit;
}
public SimpleStringProperty labelProperty(){
return this.label;
}
public SimpleObjectProperty<Relation2D> relation2DProperty(){
return this.relation2D;
}
public boolean isIncidentTo(Sommet sommet){
return (this.sommetDroit.getValue().equals(sommet) || this.sommetGauche.getValue().equals(sommet));
}
@Override
public String toString(){
return "Description de l'arete: " + this.label.getValue() + "\n"
+ "Sommet Gauche: " + this.sommetGauche.getValue().getLabel() + "\n"
+ "Sommet Droit: " + this.sommetDroit.getValue().getLabel() + "\n";
}
public ComportementPonderation getPonderation(){
return this.ponderationValue.getValue();
}
}
public class ValuePonderation implements ComportementPonderation{
private SimpleDoubleProperty ponderationValue = new SimpleDoubleProperty(0.0);
public ValuePonderation(double value){
this.setPoid(value);
}
@Override
public double getPoid() {
return this.ponderationValue.getValue();
}
@Override
public void setPoid(double poid) {
this.ponderationValue.setValue(poid);
}
@Override
public SimpleDoubleProperty poidProperty() {
return this.ponderationValue;
}
}
public interface ComportementPonderation {
public abstract double getPoid();
public abstract void setPoid(double poid);
public abstract SimpleDoubleProperty poidProperty();
}
部分控制台打印:
SD X Event:
SG: Circle[centerX=683.0, centerY=384.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
SD: Circle[centerX=694.0, centerY=384.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
---------------------------------------------
SG X Event:
SG: Circle[centerX=694.0, centerY=384.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
SD: Circle[centerX=683.0, centerY=384.0, radius=25.0, fill=0x000000ff]
---------------------------------------------
SD Y Event:
SG: Circle[centerX=683.0, centerY=384.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
SD: Circle[centerX=694.0, centerY=380.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
---------------------------------------------
SG Y Event:
SG: Circle[centerX=694.0, centerY=380.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
SD: Circle[centerX=683.0, centerY=384.0, radius=25.0, fill=0x000000ff]
---------------------------------------------
SD X Event:
SG: Circle[centerX=683.0, centerY=384.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
SD: Circle[centerX=410.0, centerY=380.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
---------------------------------------------
SG X Event:
SG: Circle[centerX=410.0, centerY=380.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
SD: Circle[centerX=683.0, centerY=384.0, radius=25.0, fill=0x000000ff]
---------------------------------------------
SD Y Event:
SG: Circle[centerX=683.0, centerY=384.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
SD: Circle[centerX=410.0, centerY=235.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
---------------------------------------------
SG Y Event:
SG: Circle[centerX=410.0, centerY=235.0, radius=25.0, fill=0xffffffff, stroke=0x000000ff, strokeWidth=2.0]
SD: Circle[centerX=683.0, centerY=384.0, radius=25.0, fill=0x000000ff]
---------------------------------------------
答案 0 :(得分:0)
我注意到的一个潜在错误:
dy
使用两次,永远不会使用dx
。
public class Relation2D extends Line{
...
private synchronized void updateComponents(double dx, double dy, Sommet2D sg, Sommet2D sd){
...
double r1x = cosAlpha * sg.getRadius();
double r1y = sinAlpha * Math.signum(dy) * sg.getRadius();
double r2x = cosAlpha * sd.getRadius();
double r2y = sinAlpha * Math.signum(dy) * sd.getRadius();
...
}
}
这可能是由于复制/粘贴错误造成的,这很常见。打开编译器警告可以帮助捕获这样的错误。在这种情况下,对未使用的方法参数的警告会警告dx
未被使用。
在Eclipse中设置此编译器警告转到Window -> Preferences -> Java -> Compiler -> Errors/Warnings -> Unnecessary code -> Value of method parameter is not used [set to Warning]
与听众相关,我注意到value
与其他observable
不同:
sg.centerXProperty().addListener((observable) -> {
System.out.println("SG X Event:");
updateComponents(dx.getValue(),dy.getValue(),sg,sd);
//updateArrowsComponents(dx.getValue(),dy.getValue());
System.out.println("---------------------------------------------");
});
// ### 'value' is the only different one, I'm not sure if it's important ###
sg.centerYProperty().addListener((value) -> {
System.out.println("SG Y Event:");
updateComponents(dx.getValue(),dy.getValue(),sg,sd);
//updateArrowsComponents(dx.getValue(),dy.getValue());
System.out.println("---------------------------------------------");
});
sd.centerXProperty().addListener((observable) -> {
System.out.println("SD X Event:");
updateComponents(dx.getValue(),dy.getValue(),sg,sd);
//updateArrowsComponents(dx.getValue(),dy.getValue());
System.out.println("---------------------------------------------");
});
sd.centerYProperty().addListener((observable) -> {
System.out.println("SD Y Event:");
updateComponents(dx.getValue(),dy.getValue(),sg,sd);
//updateArrowsComponents(dx.getValue(),dy.getValue());
System.out.println("---------------------------------------------");
});
另外,对我来说,看起来好像是Sommet Gauche X / Y事件(不是Sommet Gauche / Droit X 事件) left)centerX大于droit(右)centerX。
答案 1 :(得分:0)
解决。
我不知道是什么问题,但是从我的笔记本电脑到台式电脑的同一个项目,一切正常。
但仍然想知道为什么表演很奇怪......
对于遇到不合逻辑问题的人,我建议将项目更改为另一台计算机,可能会有用......