将文本放在javafx中的圆圈中

时间:2016-07-16 01:36:13

标签: java javafx

我目前正在尝试在Java应用程序中的圆圈中创建一系列字符。从本质上讲,短语“欢迎来到Java”将放置在一个圆圈中,从最右边开始用W.当字符沿着圆圈向下移动时,它们以一种方式旋转,使得字母的底部面向内部,按顺序形成一个圆圈。

我的代码似乎可以适当地旋转字符,但它们不会出现在窗格中心以外的任何位置。所以我的问题是:如何使用javafx实用程序将字母远离窗格中心?我的代码如下:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.geometry.Pos;

public class Characters extends Application{

@Override
public void start (Stage primaryStage){

    //Create the pane
    GridPane pane = new GridPane();
    pane.setPrefSize(600, 600);

    pane.setAlignment(Pos.CENTER);

    //Font class instance
    Font font = Font.font("Times New Roman", FontWeight.BOLD, FontPosture.REGULAR, 35);

    //Welcome to Java string
    String welcome = "Welcome to Java";
    double rotation = 90;
    double x = Math.cos(rotation)*100;
    double y = Math.sin(rotation)*100;

    //Loop
    for (int i = 0; i < welcome.length(); i++){
        x = Math.cos(Math.toRadians(rotation));
        y = Math.sin(Math.toRadians(rotation));
        System.out.println("Y: " + y);
        System.out.println("X: " + x);
        Text text = new Text(x, y, welcome.charAt(i)+"");
        System.out.println("Actual X" + text.getX());
        System.out.println("Actual Y" + text.getY());

        text.setFont(font);
        text.setRotate(rotation);
        pane.getChildren().add(text);
        rotation += 22.5;
    }

    //Create the scene for the application
    Scene scene = new Scene(pane, 500, 500);
    primaryStage.setTitle("Characters around circle");
    primaryStage.setScene(scene);
    //Display
    primaryStage.show();
}
public static void main (String [] args){
    launch(args);
}

}

3 个答案:

答案 0 :(得分:1)

GridPane基本上会忽略你的定位并决定它自己的孩子的位置。在这种情况下,所有Text元素都放在column=0; row=0) GridPane的“单元格”的中心。

我个人更喜欢将Text节点放在Group中,并将Group添加到父布局,而不是将其放在具有复杂布局算法的Parent中。

使用a Rotate transform更容易实现旋转,因为这允许您指定旋转的轴心点:

@Override
public void start(Stage primaryStage) {
    //Create the pane
    GridPane pane = new GridPane();
    pane.setAlignment(Pos.CENTER);

    Group textGroup = new Group();

    //Font class instance
    Font font = Font.font("Times New Roman", FontWeight.BOLD, FontPosture.REGULAR, 35);

    //Welcome to Java string
    String welcome = "Welcome to Java";
    double rotation = 90;

    double radius = 100d;

    //Loop
    for (char c : welcome.toCharArray()) {
        // ignore whitespace, otherwise add rotated char
        if (!Character.isWhitespace(c)) {
            Text text = new Text(Character.toString(c));
            text.setFont(font);

            Rotate rotationMatrix = new Rotate(rotation, 0, radius);
            text.getTransforms().add(rotationMatrix);

            textGroup.getChildren().add(text);
        }
        rotation += 22.5;
    }

    pane.getChildren().add(textGroup);

    //Create the scene for the application
    Scene scene = new Scene(pane, 500, 500);


    primaryStage.setTitle("Characters around circle");
    primaryStage.setScene(scene);

    //Display
    primaryStage.show();
}

结果

Resulting Application Window

答案 1 :(得分:0)

这会让你更接近你想要的结果。那里有几个错误。你不应该在这里使用GridPane,因为它的布局会干扰你的文字放置,你的公式也是错误的。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Characters extends Application {

    @Override
    public void start(Stage primaryStage) {

        // Create the pane
        // GridPane pane = new GridPane();
        Pane pane = new Pane();
        pane.setPrefSize(600, 600);

        // pane.setAlignment(Pos.CENTER);

        // Font class instance
        Font font = Font.font("Times New Roman", FontWeight.BOLD, FontPosture.REGULAR, 35);

        // Welcome to Java string
        String welcome = "Welcome to Java";
        double rotation = 90;
        double offset = pane.getPrefWidth() / 2;
        double radius = 100;
        double x = offset + Math.cos(rotation) * radius;
        double y = offset + Math.sin(rotation) * radius;

        // Loop
        for (int i = 0; i < welcome.length(); i++) {
            x = offset + Math.cos(Math.toRadians(rotation)) * radius;
            y = offset + Math.sin(Math.toRadians(rotation)) * radius;
            System.out.println("Y: " + y);
            System.out.println("X: " + x);
            Text text = new Text(x, y, welcome.charAt(i) + "");
            System.out.println("Actual X" + text.getX());
            System.out.println("Actual Y" + text.getY());

            text.setFont(font);
            text.setRotate(rotation);
            pane.getChildren().add(text);
            rotation += 22.5;
        }

        // Create the scene for the application
        // Scene scene = new Scene(pane, 500, 500);
        Scene scene = new Scene(pane);
        primaryStage.setTitle("Characters around circle");
        primaryStage.setScene(scene);
        // Display
        primaryStage.show();
    }

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

答案 2 :(得分:0)

您可以使用PathTransition执行此操作,但文本没有字距调整。所以角色看起来不太好看,我也不得不插入一些空格。也许其他一些会让它变得更好。

但作为一个不错的附加组件,如果您对该行timer.start();发表评论,那么该文字将围绕该圈旋转。

import javafx.animation.*;
import javafx.application.Application;
import javafx.collections.*;
import javafx.scene.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class BezierTextPlotter extends Application {

  private static final String CIRCLE_TEXT = "  Welcome to Java  ";

  @Override
  public void start(final Stage stage) throws Exception {

    final Text text = new Text(CIRCLE_TEXT);
    text.setStyle("-fx-font-size: 40px");

    Circle circle = new Circle(200, 200, 100);

    final ObservableList<Text> parts = FXCollections.observableArrayList();
    final ObservableList<PathTransition> transitions
            = FXCollections.observableArrayList();

    for (char character : text.textProperty().get().toCharArray()) {
      Text c = new Text(character + "");
      c.setEffect(text.getEffect());
      c.setStyle(text.getStyle());
      parts.add(c);
      transitions.add(createPathTransition(circle, c));
    }

    AnchorPane ap = new AnchorPane();
    ap.getChildren().addAll(parts);

    for (int i = 0; i < parts.size(); i++) {
      final Transition t = transitions.get(i);
      t.stop();
      t.jumpTo(Duration.seconds(10).multiply((i + 0.5) * 1.0 / parts.size()));

      AnimationTimer timer = new AnimationTimer() {
        int frameCounter = 0;

        @Override
        public void handle(long l) {
          frameCounter++;
          if (frameCounter == 1) {
            t.stop();
            stop();
          }
        }
      };
      timer.start();
      t.play();
    }

    stage.setTitle("Circle Text Sample");
    stage.setScene(new Scene(ap, 400, 400, Color.ALICEBLUE));
    stage.show();
  }

  private PathTransition createPathTransition(Shape shape, Text text) {
    final PathTransition trans
            = new PathTransition(Duration.seconds(10), shape, text);
    trans.setAutoReverse(false);
    trans.setCycleCount(PathTransition.INDEFINITE);
    trans.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT);
    trans.setInterpolator(Interpolator.LINEAR);

    return trans;
  }

  /**
   * @param args the command line arguments
   */
  public static void main(String[] args) {
    launch(args);
  }
}

enter image description here

timer.start()注释:

enter image description here