I wrote this polar clock today and i am almost finished exept i want to align my text inside the line similar to this. Does anyone know how to do this? Ive tried to use FontRenderContext and font metrics but i cant seem to get it to work. Here is the whole source code so you can compile it and see for yourselves.
import java.applet.Applet;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.Calendar;
import java.util.TimeZone;
public class Clock extends Applet implements Runnable {
int[][] colorsInt = {{20,20,20},{100,100,50},{50,100,100},{10,170,50},{79,29,245},{24,69,234},{253,24,103}};
Color[] colors;
int size;
int radius;
boolean anitalias = false;
static final float HPI = (float)(Math.PI / 180f);
public void start() {
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
new Thread(this).start();
}
public void run() {
setSize(500, 500); // For AppletViewer, remove later.
// Set up the graphics stuff, double-buffering.
BufferedImage screen = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D)screen.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
WritableRaster wr = screen.getRaster();
Graphics appletGraphics = getGraphics();
// Some variables to use for the fps.
long fpstn = 1000000000 / 600;
int tick = 0, fps = 0, acc = 0;
long lastTime = System.nanoTime();
// Vars
Calendar c;
size = 500;
radius = size / 2;
Arc2D.Float arch;
float scale, radians;
long miliSecond;
int second, minute, hour, month, year, dayOfWeek, dayOfMonth, dayOfYear, daysInMonth, daysInYear;
float[] tvars = new float[6];
float[] vars = new float[6];
String[] names = new String[6];
FontMetrics fm = g.getFontMetrics();
Font font = g.getFont();
FontRenderContext frc = g.getFontRenderContext();
GlyphVector gv = font.createGlyphVector(frc, "Hello world");
int length = gv.getNumGlyphs();
// Init
initColors();
for (int i = 0; i < vars.length; i++)
vars[i] = 0;
// Game loop.
while (true) {
long now = System.nanoTime();
acc += now - lastTime;
tick++;
if (acc >= 1000000000L) {
acc -= 1000000000L;
fps = tick;
tick = 0;
}
// Update
c = Calendar.getInstance();
miliSecond = c.get(Calendar.MILLISECOND);
second = c.get(Calendar.SECOND);
minute = c.get(Calendar.MINUTE);
hour = c.get(Calendar.HOUR_OF_DAY);
dayOfMonth = c.get(Calendar.DAY_OF_MONTH);
dayOfYear = c.get(Calendar.DAY_OF_YEAR);
dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
month = c.get(Calendar.MONTH);
daysInMonth = c.getActualMaximum(Calendar.DAY_OF_MONTH);
daysInYear = c.getActualMaximum(Calendar.DAY_OF_YEAR);
tvars[0] = (second * 1000 + miliSecond) / 60000f * 360f;
tvars[1] = (minute * 60f + second) / 3600f * 360f;
tvars[2] = (hour * 60f + minute) / 1440f * 360f;
tvars[3] = ((dayOfWeek - 2) * 24f + hour) / 168f * 360f;
tvars[4] = ((dayOfMonth - 1) * 24f + hour) / (daysInMonth * 24f) * 360f;
tvars[5] = dayOfYear / (float)daysInYear * 360f;
for (int i = 0; i < vars.length; i++) {
if (tvars[i] - vars[i] > 1) {
vars[i] += (tvars[i] - vars[i]) / 15;
} else if(tvars[i] - vars[i] < -1) {
vars[i] -= (vars[i] - tvars[i]) / 15;
} else {
vars[i] = tvars[i];
}
}
names[0] = second + " Second" + (second > 1 ? "s" : "");
lastTime = now;
// Render
g.setColor(colors[0]);
g.fillRect(0, 0, size, size);
for (int i = 0; i < vars.length; i++) {
scale = i / (float)vars.length * radius * 1.7f;
g.setColor(colors[0]);
g.fillOval((int)(scale / 2), (int)(scale / 2), (int)(size - scale), (int)(size - scale));
g.setColor(colors[i + 1]);
scale += 15;
arch = new Arc2D.Float(scale / 2, scale / 2, size - scale, size - scale, 450 - vars[i], vars[i], Arc2D.PIE);
g.fill(arch);
g.setColor(Color.WHITE);
radians = (vars[i]) * HPI;// vars[i] - 90
scale = ((float)(vars.length - i) / (float)vars.length * (float)radius / 2f * 1.7f) + 15f;
g.translate(radius, radius);
System.out.println(i + ": " + ((1 - scale / radius) * 2));
for (int j = 0; j < names[0].length(); j++) {
char ch = names[0].charAt(j);
radians = ((vars[i] - (names[0].length() - j) * 2) * (1 + (1 - scale / radius) * 2)) * HPI;
g.rotate(radians);
g.drawString(ch + "", 0, -scale);
g.rotate(-radians);
}
g.translate(-radius, -radius);
/*float x = (float)Math.cos(radians) * scale;
float y = (float)Math.sin(radians) * (vars.length - i) / vars.length * radius / 2 * 1.7f;
g.drawRect((int)x + size / 2, (int)y + size / 2, 10, 10);*/
}
scale = vars.length / (float)vars.length * radius * 1.7f;
g.setColor(colors[0]);
g.fillOval((int)(scale / 2), (int)(scale / 2), (int)(size - scale), (int)(size - scale));
g.setColor(Color.WHITE);
g.drawString("FPS " + String.valueOf(fps), 20, 30);
// Draw the entire results on the screen.
appletGraphics.drawImage(screen, 0, 0, null);
do {
Thread.yield();
} while (System.nanoTime() - lastTime < 0);
if (!isActive()) {
return;
}
}
}
public void initColors() {
colors = new Color[colorsInt.length];
for (int i = 0; i < colors.length; i++) {
colors[i] = new Color(colorsInt[i][0], colorsInt[i][1], colorsInt[i][2]);
}
}
}
Here's a simple example of rotating text.
Addendum: You'll want to adjust the the text's radial starting point by stringWidth(name[n])
. Your program appears to be rotating individual characters in a effort to follow the arc, while the example appears to be drawing the text in a straight line tangent to the arc. The latter approach may prove simpler. For example, this variation centers the labels across the arc's getStartPoint()
:
for (int i = 0; i < vars.length; i++) {
...
String s = names[0];
int w = fm.stringWidth(s);
int h = fm.getHeight() + fm.getMaxDescent();
Point2D p = arch.getStartPoint();
int x = (int) p.getX();
int y = (int) p.getY();
radians = (vars[i]) * HPI;
g.rotate(radians, x, y);
g.drawString(s, x - w / 2, y + h);
g.rotate(-radians, x, y);
}

For convenience the code above does rotate()
to and fro; for comparison, here's the original example showing repeated concatenations of rotate()
:

import java.awt.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;
/** @see http://stackoverflow.com/questions/6238037 */
public class RotateText extends JPanel {
private static final Font f = new Font("Serif", Font.BOLD, 32);
private static final String s = "Hello World!";
private static final Color[] colors = {
Color.red, Color.green, Color.blue, Color.cyan
};
private Graphics2D g2d;
private AffineTransform at;
public RotateText() {
setPreferredSize(new Dimension(400, 400));
}
@Override
public void paintComponent(Graphics g) {
g2d = (Graphics2D) g;
g2d.setFont(f);
g2d.setColor(Color.black);
g2d.fillRect(0, 0, getWidth(), getHeight());
at = g2d.getTransform();
int w = this.getWidth();
int h = this.getHeight();
int w2 = g2d.getFontMetrics().stringWidth(s) / 2;
int h2 = 2 * g2d.getFontMetrics().getHeight() / 3;
render(0, w / 2 - w2, h - h2);
render(1, h2, h / 2 - w2);
render(2, w / 2 + w2, h2);
render(3, w - h2, h / 2 + w2);
g2d.setTransform(at);
g2d.setColor(Color.yellow);
g2d.fillRect(w / 3, h / 3, w / 3, h / 3);
}
private void render(int n, int x, int y) {
g2d.setColor(colors[n]);
g2d.setTransform(at);
g2d.rotate(n * Math.PI / 2, x, y);
g2d.drawString(s, x, y);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
//@Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new RotateText(), BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
});
}
}
You have to be able to draw text along the curves. There are several ways to do it, but the simplest one is to use Stroke API. You can find an example at http://www.jhlabs.com/java/java2d/strokes/
The other way is using affine transforms. The example is at http://www.java2s.com/Code/Java/2D-Graphics-GUI/Drawtextalongacurve.htm
来源:https://stackoverflow.com/questions/6238037/how-do-i-align-this-text-correctly