java - 圆形环绕文字需要稍微调整

标签 java geometry trigonometry

您可能无法说出那么多,但由于某种原因,由于我的算法中的缺陷,一些字符正在以某种方式偏移......如果有人能找出导致它的原因,我将非常感激它和任何批评都是受欢迎的,因为我对 java 还很陌生。

enter image description here

编辑:如果您查看上图,就会发现 E 在 WE 中向左侧和右侧偏移

编辑:我认为这可能是在我对文本大小与圆圈大小的计算中

编辑:好吧,当我输入 600 的宽度和高度时,一切似乎都就位了,但是当它从 250 变小时,字符开始变得更加偏移和重叠

主类:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

/**
 * Created by John on 7/11/2014.
 */
public class Prog14_05 extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Create Pane
        circularText phrase = new circularText("WE ARE ANONYMOUS, " +
                "WE ARE LEGION, WE DO NOT FORGIVE, WE DO NOT FORGET ",
                480, 480);

        // Place clock and label in border pane
        GridPane pane = new GridPane();
        pane.setPadding(new Insets(phrase.getTextSize() * 2));
        pane.setAlignment(Pos.CENTER);
        pane.setStyle("-fx-background-color: black");
        pane.getChildren().add(phrase);

        // Create a scene and place it in the stage
        Scene scene = new Scene(pane);
        primaryStage.setTitle("Exercise14_05");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

circularText 类:

import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

/**
 * Created by John on 7/11/2014.
 */
public class circularText extends Pane {
    double textSize = 30;
    String string = "";
    String fontName = "";
    Font font;
    // Pane's width and height
    private double w = 250, h = 250;

    /** Create Constructor */
    public circularText (String phrase, double w, double h) {
        this.w = w;
        this.h = h;
        this.string = phrase;
        textSize = (this.w / this.string.length()) * 2;
        Font font = new Font("Times Roman", textSize);

        paintText(this.string, this.font);
    }

    /** Set new font */
    public void setFont(String name) {
        Font font = new Font(name, textSize);
        this.font = font;
        this.fontName = name;
        paintText(this.string, this.font);
    }

    /** Return textSize */
    public double getTextSize() {
        return this.textSize;
    }

    /** Set textSize */
    public void setTextSize(double textSize) {
        this.textSize = textSize;
        Font font = new Font(fontName, textSize);
        this.font = font;
        paintText(this.string, this.font);
    }

    /** Return pane's width */
    public double getW() {
        return w;
    }

    /** Set pane's width */
    public void setW(double w) {
        this.w = w;
        textSize = (this.w / this.string.length()) * 2;
        paintText(this.string, this.font);
    }

    /** Return pane's height */
    public double getH() {
        return h;
    }

    /** Set pane's height */
    public void setH(double h) {
        this.h = h;
        textSize = (this.w / this.string.length()) * 2;
        paintText(this.string, this.font);
    }

    /** Paint the Letters */
    protected void paintText(String phrase, Font font) {
        // Initialize parameters
        double radius = Math.min(w, h) * 0.8 * 0.5;
        double centerX = w / 2;
        double centerY = h / 2;
        double size = radius / 4 - this.getTextSize();

        // Draw circle
        Circle circle = new Circle(centerX - size - textSize, centerY - size,
            radius);
        circle.setFill(null);
        circle.setStroke(null);
        getChildren().clear();
        getChildren().add(circle);

        // Place text in a circular pattern
        int i = 0;
        double degree = 360 / phrase.length();
        for (double degrees = 0; i < phrase.length(); i++, degrees += degree) {
            double pointX = circle.getCenterX() + circle.getRadius() *
                Math.cos(Math.toRadians(degrees));
            double pointY = circle.getCenterY() + circle.getRadius() *
                Math.sin(Math.toRadians(degrees));
            Text letter = new Text(pointX, pointY, phrase.charAt(i) + "");
            letter.setFont(font);
            letter.setFill(Color.LIME);
            letter.setRotate(degrees + 90);
            getChildren().add(letter);
        }

    }
}

最佳答案

我的三角学不太好,所以我无法帮助你。我认为“W”可能被偏移,而不是“E”。我知道在 Swing 的其他版本中,“W”以前曾引起过绘画问题,但我不记得细节了。因此,我可能建议尝试不同的字符,看看您在这两个位置是否仍然遇到相同的问题。

这是我很久以前在网上找到的另一个圆形绘画的例子。我尝试了你的文字,“WE”重叠了。我将“W”更改为“R”,似乎工作正常,所以这也许验证了我上面的说法?

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Font;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GradientPaint;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
//import com.sun.awt.AWTUtilities;

public class SplashPortalPanel6 extends JPanel
{
    private static final long serialVersionUID = 1L;
//    private static final char[] MESSAGE = "  SplashPortal.net".toCharArray();
    private static final char[] MESSAGE = "  WE ARE ANONYMOUS, WE ARE LEGION, WE DO NOT FORGIVE, WE DO NOT FORGET ".toCharArray();
//    private static final char[] MESSAGE = "  RE ARE ANONYMOUS, RE ARE LEGION, RE DO NOT FORGIVE, RE DO NOT FORGET ".toCharArray();

    private static final double R90 = Math.toRadians(90);
    private static final double R_90 = Math.toRadians(-90);

    private AffineTransform cumalativeRotation = new AffineTransform();
    private double rotation = Math.toRadians(360.0 / MESSAGE.length);

    private Font font = new Font("Impact",Font.ITALIC,40);

    private final Timer timer = new Timer(1000/76, new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            repaint();//just repaint
        }
    });

    public SplashPortalPanel6() {
      setPreferredSize(new java.awt.Dimension(600, 600));
      setOpaque(false);
    }

    //This method is called when the panel is connected to a native
    //screen resource.  It's an indication we can now start painting.
    public void addNotify() {
        super.addNotify();
        timer.start();
    }
    public void removeNotify() {
        super.removeNotify();
        timer.stop();
    }

    private static final GradientPaint gradient = new GradientPaint(0F, 0F, Color.BLUE, 5F, 10F, Color.CYAN, true);

    private static final int x = 0, y = 0, w = 100, h = 100;

    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setFont(font);
        g2.translate( getWidth()/2, getHeight()/2 );
        cumalativeRotation.rotate(rotation/50);
        g2.transform( cumalativeRotation );

        for(int i = 0; i < MESSAGE.length; i++) {
            // fill the rectangle
            g2.translate(250, 0);
            g2.rotate(R90);
            g2.setColor(Color.BLACK);
//            g2.fillRect(x,y,w,h);
            // draw the border
            g2.setColor(Color.WHITE);
//            g2.drawRect(x,y,w,h);
            // draw the character
            g2.setPaint(gradient);
            g2.drawChars(MESSAGE,i, 1, x+30, y+50);
            g2.rotate(R_90);
            g2.translate(-250, 0);
            g2.rotate(rotation);
        }
    }

    public static void createAndShowSplashScreen() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setUndecorated(true);
        frame.setContentPane(new SplashPortalPanel6());
        frame.pack();
        frame.setLocationRelativeTo(null);
//        AWTUtilities.setWindowOpaque(frame, false);
        //frame.setAlwaysOnTop(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowSplashScreen();
            }
        });
    }
}

请注意,如果取消注释“fillRect”和“drawRect”语句,您将看到代码的原始实现。当然,您需要使用较短的第一条消息字符串才能看到效果。

关于java - 圆形环绕文字需要稍微调整,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24727889/

相关文章:

java - maven 跳过编译错误的测试

java - 无法在 Java 中向二叉搜索树添加 1,000,000 个元素

java - java.awt.geom适合做离散计算吗?

c - 编写余弦定律计算

java - 如何在 Android 中旋转 Rect 对象

java - servlet 如何从其他 servlet 请求数据?

algorithm - 使用 GPS 计算距离 : How to consider accuracy differences

database - 如何使用JaguarDB存储几何对象

objective-c - Obj-C 计算器 - 弧度到度数

math - 对基于数学的图像进行编程以用于高分辨率艺术品