2013-11-03 6 views
12

मैं एस को Line (पहले के केंद्र से दूसरे के केंद्र तक) से जोड़ना चाहता हूं।जावाएफएक्स: लाइन द्वारा दो नोड्स को कैसे कनेक्ट करें?

प्रारंभिक विचार:

  • यह माना जाता है कि दोनों नोड्स दृश्य ग्राफ में कहीं मौजूद
  • एक डेकोरेटर के रूप में कार्य करता है और Line pickable नहीं होना चाहिए
  • NodeBounds परिवर्तन करते हैं, तो Line

ऐसा लगता है कि मुझे कुछ यौगिक संपत्ति बाइंडिंग की आवश्यकता होगी उचित समन्वय अंतरिक्ष परिवर्तन में आईएनजी।

यह कैसे प्राप्त करने के लिए? क्या कोई दिशा निर्देश दे सकता है?

उत्तर

17

इस जवाब में कोड सवाल का जवाब पर आधारित है: CubicCurve JavaFX

नीचे दिए गए नमूना:

  • मान लिया गया है सभी नोड्स शामिल भाई बहन हैं।
  • सुनिश्चित करता है कि कनेक्टिंग लाइन लाइन पर setMouseTransparent(true) पर आक्रमण करके पिकनीय नहीं है।
  • दो एंकर नोड्स के केंद्रों को जोड़ने के लिए स्वचालित रूप से लाइन को अद्यतन करता है क्योंकि एंकर नोड्स को चारों ओर खींचा जाता है।

lines

import javafx.application.Application; 
import javafx.beans.property.*; 
import javafx.event.EventHandler; 
import javafx.scene.*; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.*; 
import javafx.stage.Stage; 

/** Example of dragging anchors around to manipulate a line. */ 
public class LineManipulator extends Application { 
    public static void main(String[] args) throws Exception { launch(args); } 
    @Override public void start(final Stage stage) throws Exception { 
    DoubleProperty startX = new SimpleDoubleProperty(100); 
    DoubleProperty startY = new SimpleDoubleProperty(100); 
    DoubleProperty endX = new SimpleDoubleProperty(300); 
    DoubleProperty endY = new SimpleDoubleProperty(200); 

    Anchor start = new Anchor(Color.PALEGREEN, startX, startY); 
    Anchor end  = new Anchor(Color.TOMATO, endX, endY); 

    Line line = new BoundLine(startX, startY, endX, endY); 
    stage.setTitle("Line Manipulation Sample"); 
    stage.setScene(new Scene(new Group(line, start, end), 400, 400, Color.ALICEBLUE)); 
    stage.show(); 
    } 

    class BoundLine extends Line { 
    BoundLine(DoubleProperty startX, DoubleProperty startY, DoubleProperty endX, DoubleProperty endY) { 
     startXProperty().bind(startX); 
     startYProperty().bind(startY); 
     endXProperty().bind(endX); 
     endYProperty().bind(endY); 
     setStrokeWidth(2); 
     setStroke(Color.GRAY.deriveColor(0, 1, 1, 0.5)); 
     setStrokeLineCap(StrokeLineCap.BUTT); 
     getStrokeDashArray().setAll(10.0, 5.0); 
     setMouseTransparent(true); 
    } 
    } 

    // a draggable anchor displayed around a point. 
    class Anchor extends Circle { 
    Anchor(Color color, DoubleProperty x, DoubleProperty y) { 
     super(x.get(), y.get(), 10); 
     setFill(color.deriveColor(1, 1, 1, 0.5)); 
     setStroke(color); 
     setStrokeWidth(2); 
     setStrokeType(StrokeType.OUTSIDE); 

     x.bind(centerXProperty()); 
     y.bind(centerYProperty()); 
     enableDrag(); 
    } 

    // make a node movable by dragging it around with the mouse. 
    private void enableDrag() { 
     final Delta dragDelta = new Delta(); 
     setOnMousePressed(new EventHandler<MouseEvent>() { 
     @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); 
     } 
     }); 
     setOnMouseReleased(new EventHandler<MouseEvent>() { 
     @Override public void handle(MouseEvent mouseEvent) { 
      getScene().setCursor(Cursor.HAND); 
     } 
     }); 
     setOnMouseDragged(new EventHandler<MouseEvent>() { 
     @Override public void handle(MouseEvent mouseEvent) { 
      double newX = mouseEvent.getX() + dragDelta.x; 
      if (newX > 0 && newX < getScene().getWidth()) { 
      setCenterX(newX); 
      } 
      double newY = mouseEvent.getY() + dragDelta.y; 
      if (newY > 0 && newY < getScene().getHeight()) { 
      setCenterY(newY); 
      } 
     } 
     }); 
     setOnMouseEntered(new EventHandler<MouseEvent>() { 
     @Override public void handle(MouseEvent mouseEvent) { 
      if (!mouseEvent.isPrimaryButtonDown()) { 
      getScene().setCursor(Cursor.HAND); 
      } 
     } 
     }); 
     setOnMouseExited(new EventHandler<MouseEvent>() { 
     @Override public void handle(MouseEvent mouseEvent) { 
      if (!mouseEvent.isPrimaryButtonDown()) { 
      getScene().setCursor(Cursor.DEFAULT); 
      } 
     } 
     }); 
    } 

    // records relative x and y co-ordinates. 
    private class Delta { double x, y; } 
    } 
} 

ऊपर कोड एक चक्र पर आधारित है, तो यह चक्र के centerX और centerY गुण को ट्रैक करने के लिए आसान है।

एक मनमाने ढंग से आकार नोड के लिए, आप यह केंद्र गुण है के भीतर यह माता पिता के नीचे दिए गए कोड का उपयोग कर ट्रैक कर सकते हैं:

:

class Center { 
    private ReadOnlyDoubleWrapper centerX = new ReadOnlyDoubleWrapper(); 
    private ReadOnlyDoubleWrapper centerY = new ReadOnlyDoubleWrapper(); 

    public Center(Node node) { 
     calcCenter(node.getBoundsInParent()); 
     node.boundsInParentProperty().addListener(new ChangeListener<Bounds>() { 
      @Override public void changed(
        ObservableValue<? extends Bounds> observableValue, 
        Bounds oldBounds, 
        Bounds bounds 
      ) { 
       calcCenter(bounds); 
      } 
     }); 
    } 

    private void calcCenter(Bounds bounds) { 
     centerX.set(bounds.getMinX() + bounds.getWidth()/2); 
     centerY.set(bounds.getMinY() + bounds.getHeight()/2); 
    } 

    ReadOnlyDoubleProperty centerXProperty() { 
     return centerX.getReadOnlyProperty(); 
    } 

    ReadOnlyDoubleProperty centerYProperty() { 
     return centerY.getReadOnlyProperty(); 
    } 
} 

ऊपर एंकर नमूना करने के लिए केंद्र कोड लागू करना, आप निम्न कोड प्राप्त

Anchor start = new Anchor(Color.PALEGREEN, startX, startY); 
Anchor end = new Anchor(Color.TOMATO, endX, endY); 

Center startCenter = new Center(start); 
Center endCenter = new Center(end); 

Line line = new BoundLine(
     startCenter.centerXProperty(), 
     startCenter.centerYProperty(), 
     endCenter.centerXProperty(), 
     endCenter.centerYProperty() 
); 

यदि आप किसी दृश्य में मनमानी नोड्स को ट्रैक करना चाहते हैं, न केवल नोड्स को झुकाएं, तो आप node.getLayoutBounds और node.getLocalToSceneTransform फ़ंक्शंस को देखना चाहेंगे।

+2

धन्यवाद, हमेशा के रूप में, बहुत उपयोगी! इसके अतिरिक्त मैं अब कस्टम बाइंडिंग का उपयोग करता हूं, 'बाइंडिंग्स .createDoubleBinding (कॉल करने योग्य , अवलोकन ...) के साथ बनाया गया है। गणना 'कॉल करने योग्य' द्वारा 'नोड.लोकलटॉसेन (बाउंड्स) 'और' नोड.sसीन टोलोकल (बाउंड्स) 'लेआउट सीमाओं के आधार पर किया जाता है। –

संबंधित मुद्दे