2017-10-06 50 views
0

我想使用JavaFX創建一個保鏢應用程序。我用Pane來顯示移動的形狀(circle, Rectange)。當我將窗口調整到更大的區域時,會發生問題。當我這樣做時,新創建的區域不會正確顯示移動的形狀。在這個新領域會發生什麼:形狀從黑色變成白色,並留下白色痕跡。JavaFX窗格不會在調整大小的區域上繪製形狀

使用setTranslateX(和Y)方法移動形狀。

我還在屏幕截圖下方提供了一個示例代碼。該代碼與錄製屏幕上的代碼不同,但它會產生相同的問題。

按照原始大小的窗口

,面積大小的窗口,其中形狀不正確繪製

命名view.fxml

<?import javafx.scene.shape.*?> 
<?import javafx.geometry.*?> 
<?import javafx.scene.control.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.AnchorPane?> 

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.company.bouncer.Controller"> 
    <center> 
     <Pane fx:id="paneField" prefHeight="344.0" prefWidth="600.0" BorderPane.alignment="CENTER" /> 
    </center> 
    <top> 
     <HBox alignment="CENTER_LEFT" prefHeight="56.0" prefWidth="600.0" spacing="30.0" BorderPane.alignment="CENTER"> 
     <children> 
      <Button fx:id="btnLaunch" mnemonicParsing="false" onAction="#handleBtn" text="Launch" /> 
     </children> 
     <opaqueInsets> 
      <Insets /> 
     </opaqueInsets> 
     <BorderPane.margin> 
      <Insets /> 
     </BorderPane.margin> 
     <padding> 
      <Insets left="30.0" /> 
     </padding> 
     </HBox> 
    </top> 
</BorderPane> 
的FXML文件

擴展應用程序的主類

package com.company.bouncer; 

import java.io.IOException; 

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


public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) throws IOException { 
     Parent root = FXMLLoader.load(getClass().getResource("/view.fxml")); 
     primaryStage.setTitle("Bouncer"); 
     primaryStage.setScene(new Scene(root, 600, 400)); 
     primaryStage.show(); 
    } 

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

    /** 
    * called when the window is closed 
    */ 
    @Override 
    public void stop() throws Exception { 
     Controller.stopExecutor(); 
     super.stop(); 
    } 
} 

** **控制器

package com.company.bouncer; 

import java.net.URL; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.ResourceBundle; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.geometry.Insets; 
import javafx.scene.control.Button; 
import javafx.scene.layout.Background; 
import javafx.scene.layout.BackgroundFill; 
import javafx.scene.layout.CornerRadii; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Rectangle; 
import javafx.scene.shape.Shape; 

public class Controller implements Initializable { 

    @FXML 
    private Button btnLaunch; 
    @FXML 
    private Pane paneField; 

    private ShapePlatform shapeRunnable; 
    private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
     shapeRunnable = new ShapePlatform(); 

     paneField.setBackground(new Background(new BackgroundFill(Color.web("#aaaaaa"), CornerRadii.EMPTY, Insets.EMPTY))); 

     executor.scheduleAtFixedRate(shapeRunnable, 0, 10, TimeUnit.MILLISECONDS); 
    } 

    @FXML 
    private void handleBtn(){ 
     shapeRunnable.generateShapeMover(); 
    } 

    public static void stopExecutor(){ 
     executor.shutdown(); 
    } 

    public class ShapePlatform implements Runnable { 

     private List<ShapeMover> shapeList = new ArrayList<>(); 

     /** 
     * Constructor 
     * @param parentPane Pane on which the shapes will be displayed 
     */ 
     public ShapePlatform(){ 
     } 

     /** 
     * creates a new shape and adds it to the shapeList 
     */ 
     public void generateShapeMover(){ 
      Shape newShape = new Rectangle(0, 0, 100, 80); 
      paneField.getChildren().add(newShape); 

      //position the object in some random location on the pane 
      newShape.setTranslateX(300); 
      newShape.setTranslateY(300); 

      //wrap it in shape mover 
      ShapeMover shapeMover = new ShapeMover(newShape); 
      shapeList.add(shapeMover); 
     } 

     /** 
     * executes one frame of moving objects 
     */ 
     private void moveAllOnce(){ 
      shapeList.forEach(sm -> sm.move()); 
     } 

     /** 
     * moves all objects, checks any intersections between objects 
     * and changes their direction if there is an intersection 
     */ 
     @Override 
     public void run() { 
      moveAllOnce(); 
     } 

     public class ShapeMover { 

      private Shape shape; 
      private int xDir = 1; 
      private int yDir = 1; 
      private int periodSpeed = 1; 
      private int periodSpeedCountDown = periodSpeed; 

      /** 
      * constructs the object 
      * @param shape - shape to be moved 
      */ 
      public ShapeMover(Shape shape){ 
       this.shape = shape; 
      } 

      /** 
      * moves object for one iteration 
      */ 
      public void move(){ 
       if(periodSpeedCountDown == 0){ 
        shape.setTranslateX(shape.getTranslateX() + xDir); 
        shape.setTranslateY(shape.getTranslateY() + yDir); 
        periodSpeedCountDown = periodSpeed; 
       } else { 
        periodSpeedCountDown--; 
       } 
      } 
     } 
    } 
} 
+1

請編輯您的問題以包含[MCVE]。 –

+0

我將代碼添加到線程中。如果你創建一個javaFX項目並且使用Main.java和Controller.java + view.fxml,那麼它應該可以工作。該軟件包名爲com.company.bouncer 該代碼與動畫中的代碼不同,但它提供了相同的問題 –

+0

您試圖從後臺線程更新UI。當你這樣做的時候結果是不確定的。爲什麼不爲動畫使用['Animation'](https://docs.oracle.com/javase/9​​/docs/api/javafx/animation/package-summary.html),而不是線程? –

回答

0

所以,這個問題實際上我是跑運動處理這可能產生我的問題後臺線程。在@James_D的建議下,我實施了使用AnimationTimer的擴展的移動處理,現在被解決的問題已經消失。

新代碼在文本下是int。我仍然必須實施一種機制來處理正確的時間,因爲現在沒有在AnimationTimer中定義的時間段。

public class Controller implements Initializable { 

    @FXML 
    private Button btnLaunch; 
    @FXML 
    private Pane paneField; 

    private ShapePlatform shapeAnimTimer; 
    private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
     paneField.setBackground(new Background(new BackgroundFill(Color.web("#aaaaaa"), CornerRadii.EMPTY, Insets.EMPTY))); 

     shapeAnimTimer = new ShapePlatform(); 
     shapeAnimTimer.start(); 
    } 

    @FXML 
    private void handleBtn(){ 
     shapeAnimTimer.generateShapeMover(); 
    } 

    public static void stopExecutor(){ 
     executor.shutdown(); 
    } 

    public class ShapePlatform extends AnimationTimer { 

     private List<ShapeMover> shapeList = new ArrayList<>(); 

     /** 
     * creates a new shape and adds it to the shapeList 
     */ 
     public void generateShapeMover(){ 
      Shape newShape = new Rectangle(0, 0, 100, 80); 
      paneField.getChildren().add(newShape); 

      //position the object in some random location on the pane 
      newShape.setTranslateX(300); 
      newShape.setTranslateY(300); 

      //wrap it in shape mover 
      ShapeMover shapeMover = new ShapeMover(newShape); 
      shapeList.add(shapeMover); 
     } 

     /** 
     * executes one frame of moving objects 
     */ 
     private void moveAllOnce(){ 
      shapeList.forEach(sm -> sm.move()); 
     } 

     /** 
     * moves all objects, checks any intersections between objects 
     * and changes their direction if there is an intersection 
     * @param now current frame 
     */ 
     @Override 
     public void handle(long now) { 
      System.out.println(now); 
      moveAllOnce(); 

     } 

     public class ShapeMover { 

      private Shape shape; 
      private int xDir = 1; 
      private int yDir = 1; 
      private int periodSpeed = 1; 
      private int periodSpeedCountDown = periodSpeed; 

      /** 
      * constructs the object 
      * @param shape - shape to be moved 
      */ 
      public ShapeMover(Shape shape){ 
       this.shape = shape; 
      } 

      /** 
      * moves object for one iteration 
      */ 
      public void move(){ 
       if(periodSpeedCountDown == 0){ 
        shape.setTranslateX(shape.getTranslateX() + xDir); 
        shape.setTranslateY(shape.getTranslateY() + yDir); 
        periodSpeedCountDown = periodSpeed; 
       } else { 
        periodSpeedCountDown--; 
       } 
      } 
     } 
    } 
} 
相關問題