2017-01-19 11 views
0

К сожалению, я не очень хорошо на английском языке ...Genarate обычай oblect и применить пользовательский файл FXML в JavaFX

Я хочу программировать "Simple UML Editor"

Use Case

Нажмите UML-холст и создайте форму UML. Курсор находится в верхней левой части UML после сгенерированного. Как this image.


Вот пример кода.

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"); 
    } 
} 

Вопросы

  1. В файле: myCircle.java. Я не могу добавить код fxmlLoader.setRoot(this);, или он покажет ошибку messege: «Значение корня уже указано». Является ли динамическая загрузка корневого узла? (Я не использовал <fx:root> или setRoot()) Если это динамическая загрузка, какой из них является моим текущим корневым узлом?

  2. В файле: myCircle.java. Я должен добавить строку this.getChildren().add(circle);, или нет генерации круга. Зачем? Я думаю, что есть некоторые важные детали, которые я не знаю ...

  3. Мне нужно centerXProperty(), чтобы реализовать функцию привязки линии привязки, но есть некоторые проблемы. Моя пользовательская форма UML применяется и загружает пользовательский файл fxml, я не мог получить настоящий centerXProperty. Я печатаю 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]. Значение всегда 0.0 независимо от того, что. Как я могу это сделать?

Я не хочу вводить код спагетти. Я купил книгу о JavaFX, но эти проблемы до сих пор беспокоит меня 4 дня ...

Спасибо :)

ответ

0
  1. Корневой элемент файла FXML является <Pane> элемент, который является в основном инструкция на FXMLLoader, чтобы создать экземпляр Pane, который становится корнем. Таким образом, когда вы пытаетесь позвонить fxmlLoader.setRoot(...), он жалуется, потому что уже есть корень, указанный в файле FXML.Чтобы это исправить, вам нужно использовать <fx:root...> в качестве корневого элемента:

    <?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> 
    

    Для того, чтобы fxmlLoader.setRoot(this) работать, this должен быть экземпляром класса, указанного атрибутом type к <fx:root>, то есть вы должны сделать myCircle подкласс 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. фиксируется фиксируя fxmlLoader.setRoot(this). Круг является дочерним элементом Pane, который является корнем файла FMXL. Раньше он не был добавлен в экземпляр myCircle, если вы не сделали этого явно.

  3. не
  4. Вы никогда не измените centerX и centerY свойствами, поэтому они всегда будут равны 0. Вы имели в виду использовать centerX="20" вместо layoutX="20" в FXML? Если вы хотите, чтобы выставить их для связывания/настройки/и т.д. Вы можете сделать это в вашем myCircle классе:

    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... 
    } 
    

    Вы могли бы также рассмотреть вопрос просто сделать MyCircle подкласс Circle, так что вы просто наследуют centerX и centerY свойства , т.е.

    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"); 
        } 
    } 
    

    , а затем

    <?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> 
    

    хотя я не уверен, если это все еще дает вам все возможности вы хотите.