【问题标题】:Draw a String with a specific angle degree in line在直线上绘制具有特定角度度数的字符串
【发布时间】:2022-01-10 03:12:17
【问题描述】:

我正在绘制一个图表,每个点的两个点都有一条带权重的线。

例如图表:点“15”到点“16”的线,权重为1.872,点“16”到点“15”,权重为1.567。

现在看看我的图表:

我想画一个始终平行(相邻)的字符串。

我计算了直线的斜率,我计算的天使是这个斜率的反正切:

我曾经使用这个函数来旋转字符串:

public static void drawRotate(Graphics2D g2d, double x, double y, double angle, String text) {
    g2d.translate((float)x,(float)y);
    g2d.rotate(Math.toRadians(angle));
    g2d.drawString(text,0,0);
    g2d.rotate(-Math.toRadians(angle));
    g2d.translate(-(float)x,-(float)y);
}

用arctan的角度((y2-y1)/(x2-x1)=直线的斜率),效果不好。

如何旋转此字符串以始终与我绘制的线平行?

我的目标:像这个例子一样绘制字符串

【问题讨论】:

  • 我不确定你所说的垂直于线是什么意思。 Imo,水平和垂直是绝对位置,所以我不明白为什么你必须旋转字符串。你的意思是垂直于线吗?你能举个例子吗?
  • @WJS 对此我很抱歉。我上传了一个例子。如果你看一看,我会很感激的。

标签: java swing graphics shapes drawstring


【解决方案1】:

这是一个快速演示,可用作如何完成它的指南。我省略了一些像箭头这样的东西,因为那只是忙碌的工作。我猜测标签位置。我建议您阅读 Graphics.rotate()RenderingHintsanti-aliasing 的三个参数版本以平滑线条。

您可能需要编写通用方法来帮助根据字体大小定位文本和标签。

但我相信您的主要问题是在计算斜率时进行 int 除法。

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GraphicsExample extends JPanel {
    JFrame f = new JFrame("Draw Vector");
    final static int WIDTH = 500;
    final static int HEIGHT = 500;
    String A = "1.567 [B->A]";
    String B = "1.862 [A->B]";
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> new GraphicsExample().start());
    }
    public void start() {
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
    public Dimension getPreferredSize() {
        return new Dimension(WIDTH, HEIGHT);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        int x1= 50;int y1 = 400;
        int x2 = 400; int y2 = 200;
        // copy the graphics context.
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int diameter = 20;
        drawLine(g2d,x1+diameter/2, y1+diameter/2, x2+diameter/2, y2+diameter/2);
        g2d.setFont(new Font("Arial", Font.PLAIN, 18));
        drawEndPoint(g2d,x1,y1, diameter, "A");
        drawEndPoint(g2d,x2,y2, diameter, "B");
        double angle = Math.atan((double)(y1-y2)/(x1-x2));
        g2d.rotate(angle,x1,y1);
        
        // based on font, this computes the placement of the Strings
        FontMetrics fm = g2d.getFontMetrics();
        int width = SwingUtilities.computeStringWidth(fm, A); // use for both
        g2d.setColor(Color.black);
        g2d.drawString(A, x1 + ((x2-x1) - width)/2, y1);
        g2d.drawString(B, x1 + ((x2-x1) - width)/2, y1+ 30);
        // discard the context.
        g2d.dispose();
    }
    
    public void drawEndPoint(Graphics2D g2d, int x, int y, int diameter, String label) {
        
        g2d.setColor(Color.BLUE);
        g2d.drawString(label, x, y);
        g2d.fillOval(x,y,diameter, diameter);
        g2d.setColor(Color.RED);
        g2d.setStroke(new BasicStroke(2f));
        g2d.drawOval(x,y,diameter, diameter);
    }
    public void drawLine(Graphics2D g2d, int x1, int y1, int x2, int y2) {
        g2d.setColor(Color.RED);
        g2d.setStroke(new BasicStroke(3f));
        g2d.drawLine(x1,y1,x2,y2);
    }
}

表演

【讨论】:

  • 为了物有所值,我赞同这个解决方案。代码上的所有内容都是按照我所知道的最佳实践完成的。从构建 Swing 应用程序到使用 Java 图形和绘画组件。
  • 这是一个很好的解决方案,我可能会提出的唯一建议是在应用转换之前制作图形上下文的“副本”,并在完成后处理副本。由于Graphics 是共享资源,因此对其应用转换(并忘记删除它)会将转换传递给下一个需要绘制的组件。而且因为我很懒,我很想将translate Graphics 偏移到旋转的中间点,然后你可以使用0x0 作为锚点;)
  • @MadProgrammer 我想到了这一点,并在调用方法之前故意设置了字体。但是在那个受控环境之外,我从来没有真正遇到过你描述的问题。在过去的测试中,我检查了Identify hashCode,并且每次都“出现”我得到一个新的图形上下文(如果这是一个可信的指示)。在上述情况下,颜色似乎恢复为默认值。但我很想知道这可能会导致问题。
  • @wjs 是的,像“颜色”(可能还有字体)这样的东西默认是作为绘画过程的一部分的组件设置,但是像转换这样的东西不是 - 我有一个开发人员的问题谁在单个组件上设置了抗锯齿,这会导致整个应用程序出现闪烁问题,根据绘制组件的顺序,跟踪和识别代码是一个完全的痛苦 - 只是因为它没有发生在你身上并不意味着它不会发生
  • @WJS 我还应该指出我使用 Java 16 在我的 Mac 上进行了快速测试,但没有产生问题,但这可能是对 Java 16 的更改或 MacOS 上的实现 - 所以,是的跨平台开发?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
  • 2015-11-18
相关资源
最近更新 更多