2016-09-03 49 views
2

你也許已經看到了一些應用程序,當在一個選項卡中的String不能完全那麼表明它是動畫,並會前後,使用戶可以看到字符串的標籤contains.Android就是幹這個是當您的手機顯示屏不足以顯示整個標籤時的設置。JavaFX的字幕動畫

下面是使用ServiceJavaFX中實現它的代碼,但它不是一個好方法。

問題是: 下面是我可以如何使用動畫或JavaFX類中的其他構建?

代碼:

import javafx.application.Platform; 
import javafx.concurrent.Service; 
import javafx.concurrent.Task; 
import javafx.scene.control.Label; 
import javafx.scene.paint.Color; 
import javafx.scene.text.Font; 
import javafx.scene.text.FontWeight; 
import tools.InfoTool; 

public class MoveTitleService extends Service<Void>{ 
    private String title; 
    volatile boolean doAnimation; 
    private int counter; 
    public Label movingText = new Label("A reallyyy big teeeeexxxxxxxxxxxxxxxxxxxxxxxt"); 


    /** 
    *Constructor 
    */ 
    public MoveTitleService() { 
     movingText.setFont(Font.font("null",FontWeight.BOLD,14)); 
     movingText.setTextFill(Color.WHITE); 

     setOnSucceeded(s ->{ 
      movingText.setText(""); 
     }); 
    } 

    //Start the Service 
    public void startTheService(String title) { 
     this.title = title; 
     doAnimation = true; 

     restart(); 
    } 


    //Stop the Service 
    public void stopService(){ 
     doAnimation=false; 
    } 

    @Override 
    protected Task<Void> createTask() { 
     return new Task<Void>() { 
      @Override 
      protected Void call() throws Exception { 

       while (doAnimation) { 
        //System.out.println("MoveTitleService is Running..."); 

        // One letter at a time 
        for (int m = 0; m <= title.length(); m++) { 
         counter=m; 

         Platform.runLater(() ->{ 
          movingText.setText(title.substring(0, counter) + addSpaces(title.length() - counter));  
         }); 

         if(!doAnimation) break; 
         Thread.sleep(150); 
        } 

        // Disappearing to back 
        for (int m = 0; m < title.length(); m++) { 
         counter=m; 

         Platform.runLater(() ->{ 
          movingText.setText(title.substring(counter)); 
         }); 

         if(!doAnimation) break; 
         Thread.sleep(150); 
        } 

        // Appearing to front 
        for (int m = 1; m <= title.length(); m++) { 
         counter=m; 

         Platform.runLater(() ->{ 
          movingText.setText(title.substring(title.length() - counter)); 
         }); 

         if(!doAnimation) break; 
         Thread.sleep(150); 
        } 

        if(!doAnimation) break; 
        for(int i=0; i<3000/150; i++) 
         Thread.sleep(150); 
        Thread.sleep(3000); 

       } 

       return null; 
      } 

      private String addSpaces(int spaces) { 
       String z = ""; 
       for (int i = 0; i <= spaces; i++) 
        z += " "; 

       return z; 
      } 

     }; 
    } 

} 

回答

2

你可以使用這個Timeline

// min distance to Pane bounds 
private static final double OFFSET = 25; 

@Override 
public void start(Stage primaryStage) { 
    Text text = new Text("A reallyyy big teeeeexxxxxxxxxxxxxxxxxxxxxxxt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 
    text.setLayoutY(25); 
    text.setManaged(false); 
    text.setLayoutX(OFFSET); 

    Pane pane = new Pane(text); 
    pane.setMinHeight(50); 

    Timeline timeline = new Timeline(); 

    KeyFrame updateFrame = new KeyFrame(Duration.seconds(1/60d), new EventHandler<ActionEvent>() { 

     private boolean rightMovement; 

     @Override 
     public void handle(ActionEvent event) { 
      double tW = text.getLayoutBounds().getWidth(); 
      double pW = pane.getWidth(); 
      double layoutX = text.getLayoutX(); 

      if (2 * OFFSET + tW <= pW && layoutX >= OFFSET) { 
       // stop, if the pane is large enough and the position is correct 
       text.setLayoutX(OFFSET); 
       timeline.stop(); 
      } else { 
       if ((rightMovement && layoutX >= OFFSET) || (!rightMovement && layoutX + tW + OFFSET <= pW)) { 
        // invert movement, if bounds are reached 
        rightMovement = !rightMovement; 
       } 

       // update position 
       if (rightMovement) { 
        layoutX += 1; 
       } else { 
        layoutX -= 1; 
       } 
       text.setLayoutX(layoutX); 
      } 
     } 
    }); 

    timeline.getKeyFrames().add(updateFrame); 
    timeline.setCycleCount(Animation.INDEFINITE); 

    // listen to bound changes of the elements to start/stop the animation 
    InvalidationListener listener = o -> { 
     double textWidth = text.getLayoutBounds().getWidth(); 
     double paneWidth = pane.getWidth(); 
     if (textWidth + 2 * OFFSET > paneWidth 
       && timeline.getStatus() != Animation.Status.RUNNING) { 
      timeline.play(); 
     } 
    }; 

    text.layoutBoundsProperty().addListener(listener); 
    pane.widthProperty().addListener(listener); 

    Scene scene = new Scene(pane); 

    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

注意repeadedly更新自己需要做的事情,因爲運行時Animation s不能進行調整的位置,所以對於任何大小調整到動畫中生效,你需要反覆更新...

+0

我得到一個錯誤「關鍵幀(時間,新的事件處理程序(){})是未定義」在第31行.. – GOXR3PLUS

+0

@ GoXR3Plus:你有沒有加入正確的進口,即進口'javafx.animation.KeyFrame; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.util.Duration;'? – fabian

+0

我現在面臨的一些問題與上面的代碼:)你可以看一下http://stackoverflow.com/questions/40990292/javafx-text-is-overlapping-other-layout-elements-when-using-translatex-或者 - tran問題?感謝你的回答 ... – GOXR3PLUS