| | |
Trying to draw text at an angle
Please support our Java advertiser: Programming Forums - DaniWeb Sister Site
Thread Solved |
•
•
Join Date: Jan 2008
Posts: 3,844
Reputation:
Solved Threads: 503
•
•
•
•
yes, the blurry text is because of int rounding error. a better way to do it would be affinetransform, but i haven't used it much, and the sun tutorial confused me a bit, i think that this may also help.
You have made this a bit more complex than need be. For simple transformations, the Graphics2D methods rotate() and translate() will suffice (they additively modify the current AffineTransform of the graphics context) without any need to obtain or work with an AffineTransform object directly.
I wrote this small example that might help
I wrote this small example that might help
java Syntax (Toggle Plain Text)
import java.awt.BorderLayout; import java.awt.Color; import java.awt.EventQueue; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JFrame; import javax.swing.JPanel; public class TextExample extends JFrame { GraphicPanel gPanel; public TextExample() { setDefaultCloseOperation(EXIT_ON_CLOSE); setLayout(new BorderLayout()); gPanel = new GraphicPanel(); getContentPane().add(gPanel, BorderLayout.CENTER); setBounds(100, 100, 200, 200); setVisible(true); } class GraphicPanel extends JPanel { protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D)g; g2.setBackground(Color.BLACK); g2.clearRect(0, 0, getWidth(), getHeight()); g2.setColor(Color.WHITE); String msg = "Hi Vernon"; FontMetrics metrics = g2.getFontMetrics(); // translate context to center of panel // the point 0,0 now resides here g2.translate(getWidth() / 2, getHeight() / 2); g2.drawString(msg, -metrics.stringWidth(msg) / 2, metrics.getMaxAscent() / 2); // rotate 45 deg g2.rotate(-Math.PI / 4); g2.setColor(Color.YELLOW); g2.drawString(msg, -metrics.stringWidth(msg) / 2, metrics.getMaxAscent() / 2); // rotate 45 deg again - these transforms are additive g2.rotate(-Math.PI / 4); g2.setColor(Color.ORANGE); g2.drawString(msg, -metrics.stringWidth(msg) / 2, metrics.getMaxAscent() / 2); } } public static void main(String... args) { EventQueue.invokeLater(new Runnable() { public void run() { new TextExample(); } }); } }
•
•
Join Date: Jan 2008
Posts: 3,844
Reputation:
Solved Threads: 503
•
•
•
•
You have made this a bit more complex than need be. For simple transformations, the Graphics2D methods rotate() and translate() will suffice (they additively modify the current AffineTransform of the graphics context) without any need to obtain or work with an AffineTransform object directly.
I wrote this small example that might helpjava Syntax (Toggle Plain Text)
import java.awt.BorderLayout; import java.awt.Color; import java.awt.EventQueue; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JFrame; import javax.swing.JPanel; public class TextExample extends JFrame { GraphicPanel gPanel; public TextExample() { setDefaultCloseOperation(EXIT_ON_CLOSE); setLayout(new BorderLayout()); gPanel = new GraphicPanel(); getContentPane().add(gPanel, BorderLayout.CENTER); setBounds(100, 100, 200, 200); setVisible(true); } class GraphicPanel extends JPanel { protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D)g; g2.setBackground(Color.BLACK); g2.clearRect(0, 0, getWidth(), getHeight()); g2.setColor(Color.WHITE); String msg = "Hi Vernon"; FontMetrics metrics = g2.getFontMetrics(); // translate context to center of panel // the point 0,0 now resides here g2.translate(getWidth() / 2, getHeight() / 2); g2.drawString(msg, -metrics.stringWidth(msg) / 2, metrics.getMaxAscent() / 2); // rotate 45 deg g2.rotate(-Math.PI / 4); g2.setColor(Color.YELLOW); g2.drawString(msg, -metrics.stringWidth(msg) / 2, metrics.getMaxAscent() / 2); // rotate 45 deg again - these transforms are additive g2.rotate(-Math.PI / 4); g2.setColor(Color.ORANGE); g2.drawString(msg, -metrics.stringWidth(msg) / 2, metrics.getMaxAscent() / 2); } } public static void main(String... args) { EventQueue.invokeLater(new Runnable() { public void run() { new TextExample(); } }); } }
Yes, some of their examples can be more complex than need be and obscure the usage they are trying to demonstrate. 
One more thing worth noting with respect to AffineTransforms is that they represent the current state of the coordinate system within the graphics context. Since you can store references to as many AffineTransforms as you want, you can effectively "save" any state (translation, orientation, scale, and sheer) you wish and restore it at will. If you have many objects that render themselves independently, each can maintain it's own transform that it uses for rendering. When that object's turn to be rendered comes, you can save the current transform of your graphics context, apply that object's transform, render it, and then restore the original transform.
Here's an example of that:

One more thing worth noting with respect to AffineTransforms is that they represent the current state of the coordinate system within the graphics context. Since you can store references to as many AffineTransforms as you want, you can effectively "save" any state (translation, orientation, scale, and sheer) you wish and restore it at will. If you have many objects that render themselves independently, each can maintain it's own transform that it uses for rendering. When that object's turn to be rendered comes, you can save the current transform of your graphics context, apply that object's transform, render it, and then restore the original transform.
Here's an example of that:
java Syntax (Toggle Plain Text)
import java.awt.BorderLayout; import java.awt.Color; import java.awt.EventQueue; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.geom.AffineTransform; import javax.swing.JFrame; import javax.swing.JPanel; public class TransformExample extends JFrame { GraphicPanel gPanel; public TransformExample() { setDefaultCloseOperation(EXIT_ON_CLOSE); gPanel = new GraphicPanel(); getContentPane().add(gPanel); setBounds(100, 100, 200, 200); setVisible(true); } class GraphicPanel extends JPanel { TextLabel label1; TextLabel label2; TextLabel label3; protected void paintComponent(Graphics g) { if (label1 == null) { // lazy initilization so I have dimensions to work with FontMetrics fm = g.getFontMetrics(); int width = getWidth(); int height = getHeight(); label1 = new TextLabel("Hi Vernon", Color.YELLOW, 20, height/2, -Math.PI/2); String labelText = "I'm over here"; int labelLen = fm.stringWidth(labelText); label2 = new TextLabel(labelText, Color.CYAN, width-labelLen, height/2, -Math.PI/4); labelText = "Standing on my head"; labelLen = fm.stringWidth(labelText); label3 = new TextLabel(labelText, Color.ORANGE, (width+labelLen)/2, height-20, Math.PI); } Graphics2D g2 = (Graphics2D)g; g2.setBackground(Color.BLACK); g2.clearRect(0, 0, getWidth(), getHeight()); label1.draw(g2); label2.draw(g2); label3.draw(g2); } } class TextLabel { private AffineTransform transform; private Point location; private double rotation; private String text; private Color color; public TextLabel(String text, Color color, int x, int y, double rotation) { this.text = text; this.color = color; this.location = new Point(x, y); this.rotation = rotation; transform = new AffineTransform(); transform.translate(location.x, location.y); transform.rotate(rotation); } public void draw(Graphics2D g){ // save current color and transform AffineTransform currentTransform = g.getTransform(); Color currentColor = g.getColor(); // apply my own color and transform g.setTransform(transform); g.setColor(color); // this will be left aligned at the origin // a parameter for left/center/right alignment // could be added easily g.drawString(text, 0, 0); // restore the original state g.setColor(currentColor); g.setTransform(currentTransform); } } public static void main(String... args) { EventQueue.invokeLater(new Runnable() { public void run() { new TransformExample(); } }); } }
•
•
Join Date: Jan 2008
Posts: 3,844
Reputation:
Solved Threads: 503
•
•
•
•
Yes, some of their examples can be more complex than need be and obscure the usage they are trying to demonstrate.
One more thing worth noting with respect to AffineTransforms is that they represent the current state of the coordinate system within the graphics context. Since you can store references to as many AffineTransforms as you want, you can effectively "save" any state (translation, orientation, scale, and sheer) you wish and restore it at will. If you have many objects that render themselves independently, each can maintain it's own transform that it uses for rendering. When that object's turn to be rendered comes, you can save the current transform of your graphics context, apply that object's transform, render it, and then restore the original transform.
Here's an example of that:
Perfect! My project is a type of ColorForms/CAD program where the user can draw pentagons, ovals, rectangles, text, etc., on the screen and they can all be different sizes and different angles and I'm going to try to give the option where a user can spin one shape and/or piece of text and leave the others the same or spin them all or spin some but not others or change one or more sizes, etc. Potentially you could have hundreds or even thousands of objects on the screen, all with different sizes and different angles. To rotate a polygon, I was doing the math and changing the polygon coordinates myself, but the idea of keeping the same points and having a different AffineTransformation for each of them is very appealing and seems like less calculation for me. Plus the goal is to be able to tilt images too eventually. This method has fantastic potential compared to my earlier approach. Thanks again. As usual, you gave great sample code.
Last edited by VernonDozier; Aug 26th, 2008 at 9:29 pm.
![]() |
Similar Threads
- Turtle graph (Python)
- Graphical Barcode Control (C#)
- Tutorial: Photoshop: create a tabbed navigation bar (Graphics and Multimedia)
- URGENT!! - Constructive Criticism needed on www.giftday.co.za (Website Reviews)
- Identifying Drivers needed (Windows 95 / 98 / Me)
Other Threads in the Java Forum
- Previous Thread: Clean up my code
- Next Thread: Socket problems
Views: 3161 | Replies: 14
| Thread Tools | Search this Thread |
Tag cloud for affinetransform, graphics, rotatetext







