2017-01-19 1 views
0

Désolé, je ne suis pas bon en anglais ...Genarate un oblect personnalisé et appliquer le fichier FXML personnalisé dans JavaFX

Je veux programmer un "UML Simple Editor"

cas d'utilisation

Cliquez sur le canevas UML et générez une forme UML. Le curseur est au sommet gauche de la forme UML après avoir été généré. Comme this image.


est un exemple de code ici.

Main.java

package application; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 


public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) { 
     try { 
      Parent root = FXMLLoader.load(getClass().getResource("mainView.fxml")); 
      Scene scene = new Scene(root); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

mainView.fxml

<?xml version="1.0" encoding="UTF-8"?> 

<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 


<Pane fx:id="canvas" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" onMouseClicked="#onMouseClicked" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainViewController" /> 

MainViewController.java

package application; 

import javafx.fxml.FXML; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.Pane; 

public class MainViewController { 

    @FXML Pane canvas; 

    @FXML private void onMouseClicked(MouseEvent event) { 
     myCircle c = new myCircle(); 

     c.setLayoutX(event.getX()); 
     c.setLayoutY(event.getY()); 
     canvas.getChildren().add(c); 
    } 
} 

myCircle.fxml

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.shape.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.Scene?> 

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="40.0" prefWidth="40.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> 
    <children> 
     <Circle fx:id="circle" fill="DODGERBLUE" layoutX="20.0" layoutY="20.0" radius="20.0" stroke="BLACK" strokeType="INSIDE" /> 
    </children> 
</Pane> 

myCircle.java

package application; 

import java.io.IOException; 

import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.layout.Parent; 
import javafx.scene.shape.Circle; 

public class myCircle extends Parent { 

    @FXML Circle circle; 

    public myCircle() { 
     // TODO Auto-generated constructor stub 
     FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("myCircle.fxml")); 
     //fxmlLoader.setRoot(this); 
     fxmlLoader.setController(this); 
     try { 
      fxmlLoader.load(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     this.getChildren().add(circle); 

     System.out.println("generate myCircle"); 
    } 
} 

Questions

  1. Dans le fichier: myCircle.java. Je ne peux pas ajouter le code fxmlLoader.setRoot(this);, ou il affichera l'erreur messege: "Valeur racine déjà spécifiée." Le chargement du noeud racine est-il dynamique? (Je n'ai pas utilisé <fx:root> ou setRoot()) S'il s'agit d'un chargement dynamique, lequel est mon nœud racine actuel?

  2. Dans le fichier: myCircle.java. Je dois ajouter la ligne this.getChildren().add(circle);, ou il n'y a pas de cercle générer. Pourquoi? Je pense qu'il y a un détail important que je ne connais pas ...

  3. J'ai besoin de centerXProperty() pour implémenter la fonction relative à la ligne de reliure, mais il y a un problème. Ma forme UML personnalisée s'applique et charge le fichier fxml personnalisé, je ne pouvais pas obtenir le vrai centreXProperty. J'imprime centerXProperty messege: DoubleProperty [bean: Circle[id=circle, centerX=0.0, centerY=0.0, radius=20.0, fill=0x1e90ffff, stroke=0x000000ff, strokeWidth=1.0], name: centerX, value: 0.0]. La valeur est toujours 0.0 peu importe quoi. Comment pourrais-je faire?

Je ne veux pas taper le code spaghetti. Je l'ai acheté un livre sur JavaFX, mais ces problèmes encore pris la peine de me 4 jours ...

Merci :)

Répondre

0
  1. L'élément racine de votre fichier FXML est un élément <Pane>, qui est essentiellement une instruction pour créer une instance Pane, qui devient la racine. Ainsi, lorsque vous essayez d'appeler fxmlLoader.setRoot(...), il se plaint, car il existe déjà une racine spécifiée dans le fichier FXML.Pour résoudre ce problème, vous devez utiliser <fx:root...> comme l'élément racine:

    <?xml version="1.0" encoding="UTF-8"?> 
    
    <?import javafx.scene.shape.*?> 
    <?import java.lang.*?> 
    <?import javafx.scene.layout.*?> 
    <?import javafx.scene.Scene?> 
    
    <fx:root type="Pane" maxHeight="-Infinity" maxWidth="-Infinity" 
        minHeight="-Infinity" minWidth="-Infinity" 
        prefHeight="40.0" prefWidth="40.0" 
        xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> 
        <children> 
         <Circle fx:id="circle" fill="DODGERBLUE" layoutX="20.0" layoutY="20.0" radius="20.0" stroke="BLACK" strokeType="INSIDE" /> 
        </children> 
    </fx:root> 
    

    Pour fxmlLoader.setRoot(this) au travail, this doit être une instance de la classe spécifiée par l'attribut type à <fx:root>, à savoir que vous devez faire myCircle une sous-classe de Pane:

    package application; 
    
    import java.io.IOException; 
    
    import javafx.fxml.FXML; 
    import javafx.fxml.FXMLLoader; 
    import javafx.scene.layout.Pane; 
    import javafx.scene.shape.Circle; 
    
    public class myCircle extends Pane { 
    
        @FXML Circle circle; 
    
        public myCircle() { 
         // TODO Auto-generated constructor stub 
         FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("myCircle.fxml")); 
         fxmlLoader.setRoot(this); 
         fxmlLoader.setController(this); 
         try { 
          fxmlLoader.load(); 
         } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
    
         // circle is now added to this by the FXML. 
         // So next line is no longer needed: 
         // this.getChildren().add(circle); 
    
         System.out.println("generate myCircle"); 
        } 
    } 
    
  2. est fixé par fixation fxmlLoader.setRoot(this). Le cercle est un enfant du Pane qui est la racine du fichier FMXL. Auparavant, il n'était pas ajouté à l'instance myCircle sauf si vous l'aviez explicitement fait.

  3. Vous ne modifier les propriétés centerX et centerY, donc ils seront toujours 0. Vouliez-vous dire utiliser centerX="20" au lieu de layoutX="20" dans le FXML? Si vous voulez les exposer pour la liaison/configuration/etc vous pouvez le faire dans votre myCircle classe:

    package application; 
    
    import java.io.IOException; 
    
    import javafx.beans.property.DoubleProperty ; 
    import javafx.fxml.FXML; 
    import javafx.fxml.FXMLLoader; 
    import javafx.scene.layout.Pane; 
    import javafx.scene.shape.Circle; 
    
    public class myCircle extends Pane { 
    
        @FXML Circle circle; 
    
        public myCircle() { 
         // TODO Auto-generated constructor stub 
         FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("myCircle.fxml")); 
         fxmlLoader.setRoot(this); 
         fxmlLoader.setController(this); 
         try { 
          fxmlLoader.load(); 
         } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
    
         // circle is now added to this by the FXML. 
         // So next line is no longer needed: 
         // this.getChildren().add(circle); 
    
         System.out.println("generate myCircle"); 
        } 
    
        public DoubleProperty centerXProperty() { 
         return circle.centerXProperty(); 
        } 
    
        public final double getCenterX() { 
         return centerXProperty().get(); 
        } 
    
        public final void setCenterX(double centerX) { 
         centerXProperty().set(centerX); 
        } 
    
        // same for centerY... 
    } 
    

    Vous pouvez également envisager simplement faire MyCircle une sous-classe de Circle, de sorte que vous héritez simplement les centerX et centerY propriétés . à savoir

    package application; 
    
    import java.io.IOException; 
    
    import javafx.fxml.FXML; 
    import javafx.fxml.FXMLLoader; 
    import javafx.scene.shape.Circle; 
    
    public class myCircle extends Circle { 
    
        public myCircle() { 
         // TODO Auto-generated constructor stub 
         FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("myCircle.fxml")); 
         fxmlLoader.setRoot(this); 
         fxmlLoader.setController(this); 
         try { 
          fxmlLoader.load(); 
         } catch (IOException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
    
         System.out.println("generate myCircle"); 
        } 
    } 
    

    puis

    <?xml version="1.0" encoding="UTF-8"?> 
    
    <?import javafx.scene.shape.*?> 
    <?import java.lang.*?> 
    <?import javafx.scene.layout.*?> 
    <?import javafx.scene.Scene?> 
    
    <fx:root type="Circle" fill="DODGERBLUE" layoutX="20.0" layoutY="20.0" 
        radius="20.0" stroke="BLACK" strokeType="INSIDE" 
        xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> 
    </fx:root> 
    

    si je ne sais pas si cela vous donne encore toutes les fonctionnalités que vous voulez.