Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #31890 > unrolled thread

Image rotation part 2

Started byMartin Gregorie <martin@address-in-sig.invalid>
First post2015-06-30 16:55 +0000
Last post2015-07-29 05:35 -0700
Articles 18 — 7 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Image rotation part 2 Martin Gregorie <martin@address-in-sig.invalid> - 2015-06-30 16:55 +0000
    Re: Image rotation part 2 Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-06-30 14:03 -0400
      Re: Image rotation part 2 Martin Gregorie <martin@address-in-sig.invalid> - 2015-06-30 20:04 +0000
        Re: Image rotation part 2 Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-06-30 16:20 -0400
          Re: Image rotation part 2 Martin Gregorie <martin@address-in-sig.invalid> - 2015-06-30 20:52 +0000
    Re: Image rotation part 2 e.d.programmer@gmail.com - 2015-06-30 12:07 -0700
    Re: Image rotation part 2 Martin Gregorie <martin@address-in-sig.invalid> - 2015-06-30 20:18 +0000
    Re: Image rotation part 2 Jeff Higgins <jeff@invalid.invalid> - 2015-06-30 19:04 -0400
      Re: Image rotation part 2 Knute Johnson <nospam@rabbitbrush.frazmtn.com> - 2015-06-30 16:36 -0700
        Re: Image rotation part 2 Jeff Higgins <jeff@invalid.invalid> - 2015-06-30 20:17 -0400
      Re: Image rotation part 2 Jeff Higgins <jeff@invalid.invalid> - 2015-06-30 20:09 -0400
      Re: Image rotation part 2 e.d.programmer@gmail.com - 2015-07-01 06:06 -0700
        Re: Image rotation part 2 FredK <fred.l.kleinschmidt@gmail.com> - 2015-07-01 10:57 -0700
        Re: Image rotation part 2 Jeff Higgins <jeff@invalid.invalid> - 2015-07-01 18:13 -0400
        Re: Image rotation part 2 Arne Vajhøj <arne@vajhoej.dk> - 2015-07-27 22:28 -0400
          Re: Image rotation part 2 e.d.programmer@gmail.com - 2015-07-28 04:58 -0700
            Re: Image rotation part 2 Arne Vajhøj <arne@vajhoej.dk> - 2015-07-28 18:58 -0400
              Re: Image rotation part 2 e.d.programmer@gmail.com - 2015-07-29 05:35 -0700

#31890 — Image rotation part 2

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2015-06-30 16:55 +0000
SubjectImage rotation part 2
Message-ID<mmuhle$gp1$1@dont-email.me>
Thanks to help from Knute about five 11 months ago I was able to create 
JLabel subclasses that could display vertically aligned text, e.g.

   N
   a
   m
   e

by using HTML text, e.g. "<html>N<br>a<br>m<br>e</html>" This works well, 
except that some of the longer names create very tall instances that use 
up more screen than I can really spade (the row of names is near the top 
of a matrix which has 50+ lines below it, so it would be nice to avoid as 
much scrolling up and down as possible. 

Having noticed that most Monospaced characters are just over half as wide 
as they are high, I'm again thinking about somehow standing the character 
string on end by rotating it through 90 degrees. I'm successfully 
creating a JPG image containing black 10 pt Monospaced text on a 
LIGHT_GRAY background within a minimal window (20 pixels high and 
s.length() * (fontsize * 7 / 10) wide, whenever I try to rotate it, all 
I'm getting is a solid black image thats rotated so its longest dimension 
is now vertical. 

The code looks like this:

   BufferedImage im = new BufferedImage(width,
                                        height,
                                        BufferedImage.TYPE_INT_RGB);

   // image created in im

   BufferedImage om = new BufferedImage(height,
                                        width,
                                        BufferedImage.TYPE_INT_RGB);
   AffineTransform at = new AffineTransform();
   at.setToQuadrantRotation(-1);
   AffineTransformOp aop = new AffineTransformOp(at,
                               AffineTransformOp.TYPE_BILINEAR);
   aop.filter(im, om);

I've also tried setting the AffineTransformOp to TYPE_BICUBIC but that 
also gave a black rectangle.

I'm obviously doing something stupid or have missed out a vital step, but 
what?


-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [next] | [standalone]


#31891

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-06-30 14:03 -0400
Message-ID<mmulii$b3u$1@dont-email.me>
In reply to#31890
On 6/30/2015 12:55 PM, Martin Gregorie wrote:
> [...]I'm again thinking about somehow standing the character
> string on end by rotating it through 90 degrees. I'm successfully
> creating a JPG image containing black 10 pt Monospaced text on a
> LIGHT_GRAY background within a minimal window (20 pixels high and
> s.length() * (fontsize * 7 / 10) wide, whenever I try to rotate it, all
> I'm getting is a solid black image thats rotated so its longest dimension
> is now vertical.
>
> The code looks like this:
>
>     BufferedImage im = new BufferedImage(width,
>                                          height,
>                                          BufferedImage.TYPE_INT_RGB);
>
>     // image created in im
>
>     BufferedImage om = new BufferedImage(height,
>                                          width,
>                                          BufferedImage.TYPE_INT_RGB);
>     AffineTransform at = new AffineTransform();
>     at.setToQuadrantRotation(-1);

     This may be the problem: You're rotating the image a quarter-turn,
but not moving the origin.  I think that means you're rotating the
"payload" pixels clear out of the area that then fills the destination.
(Think about a closed door: After rotating it a quarter-turn about its
hinges, how much of the rotated door remains within the doorframe?)

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31898

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2015-06-30 20:04 +0000
Message-ID<mmusni$m87$1@dont-email.me>
In reply to#31891
On Tue, 30 Jun 2015 14:03:17 -0400, Eric Sosman wrote:

> On 6/30/2015 12:55 PM, Martin Gregorie wrote:
>> [...]I'm again thinking about somehow standing the character string on
>> end by rotating it through 90 degrees. I'm successfully creating a JPG
>> image containing black 10 pt Monospaced text on a LIGHT_GRAY background
>> within a minimal window (20 pixels high and s.length() * (fontsize * 7
>> / 10) wide, whenever I try to rotate it, all I'm getting is a solid
>> black image thats rotated so its longest dimension is now vertical.
>>
>> The code looks like this:
>>
>>     BufferedImage im = new BufferedImage(width,
>>                                          height,
>>                                          BufferedImage.TYPE_INT_RGB);
>>
>>     // image created in im
>>
>>     BufferedImage om = new BufferedImage(height,
>>                                          width,
>>                                          BufferedImage.TYPE_INT_RGB);
>>     AffineTransform at = new AffineTransform();
>>      
> 
>      This may be the problem: You're rotating the image a quarter-turn,
> but not moving the origin.  I think that means you're rotating the
> "payload" pixels clear out of the area that then fills the destination.
> (Think about a closed door: After rotating it a quarter-turn about its
> hinges, how much of the rotated door remains within the doorframe?)

If I understand correctly that implies a one line change, replacing

   at.setToQuadrantRotation(-1); 

with

   at.setToQuadrantRotation(direction,  
                            new Double(width/2),
                            new Double(height/2));
   
which, sadly just produced another solid black image.
Is there a decent tutorial anywhere about using Affine transforms? I'm 
pretty much out of my depth when it comes to this sort of thing.


-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#31900

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-06-30 16:20 -0400
Message-ID<mmutjf$hcb$1@dont-email.me>
In reply to#31898
On 6/30/2015 4:04 PM, Martin Gregorie wrote:
> On Tue, 30 Jun 2015 14:03:17 -0400, Eric Sosman wrote:
>
>> On 6/30/2015 12:55 PM, Martin Gregorie wrote:
>>> [...]I'm again thinking about somehow standing the character string on
>>> end by rotating it through 90 degrees. I'm successfully creating a JPG
>>> image containing black 10 pt Monospaced text on a LIGHT_GRAY background
>>> within a minimal window (20 pixels high and s.length() * (fontsize * 7
>>> / 10) wide, whenever I try to rotate it, all I'm getting is a solid
>>> black image thats rotated so its longest dimension is now vertical.
>>>
>>> The code looks like this:
>>>
>>>      BufferedImage im = new BufferedImage(width,
>>>                                           height,
>>>                                           BufferedImage.TYPE_INT_RGB);
>>>
>>>      // image created in im
>>>
>>>      BufferedImage om = new BufferedImage(height,
>>>                                           width,
>>>                                           BufferedImage.TYPE_INT_RGB);
>>>      AffineTransform at = new AffineTransform();
>>>
>>
>>       This may be the problem: You're rotating the image a quarter-turn,
>> but not moving the origin.  I think that means you're rotating the
>> "payload" pixels clear out of the area that then fills the destination.
>> (Think about a closed door: After rotating it a quarter-turn about its
>> hinges, how much of the rotated door remains within the doorframe?)
>
> If I understand correctly that implies a one line change, replacing
>
>     at.setToQuadrantRotation(-1);
>
> with
>
>     at.setToQuadrantRotation(direction,
>                              new Double(width/2),
>                              new Double(height/2));
>
> which, sadly just produced another solid black image.
> Is there a decent tutorial anywhere about using Affine transforms? I'm
> pretty much out of my depth when it comes to this sort of thing.

     I've used them a few times, but find them confusing -- in part
because the Y axis is inverted from The Way We Learned In School, which
is The Way I Always Picture It In My Foggy Little Brain.  Basically,
though, I think the best way to build the transform you want is to
compose it out of simpler steps.  In your case, the steps would be

	1) Translate the center of your image to the origin,
	2) Rotate the image a quarter-turn (rotation about the
	   origin is now rotation about the image's center),
	3) Translate the origin to the center of the new image.

You can build these three transforms (it would take me a few tries to
get the translations right; see Y axis, above) and combine them into a
single transform (it would take me a few tries to get the order right;
matrix multiplication is not commutative but at least you know that the
rotation step is in the middle), and then apply the combined super-
transform to your image.

     Applying your transform to a (non-square) Rectangle and simply
printing the original and transformed coordinates might help debug.
Good luck!

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31901

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2015-06-30 20:52 +0000
Message-ID<mmuvj8$m87$4@dont-email.me>
In reply to#31900
On Tue, 30 Jun 2015 16:20:17 -0400, Eric Sosman wrote:

>      I've used them a few times, but find them confusing -- in part
> because the Y axis is inverted from The Way We Learned In School, which
> is The Way I Always Picture It In My Foggy Little Brain.
>
I'm OK with that part due to a lot of time spent working with 
alphanumeric terminals - VT52, VT100, WY-120 etc. They all treat the top 
left corner of the screen as the origin.

> 	1) Translate the center of your image to the origin, 2) Rotate the
> 	image a quarter-turn (rotation about the
> 	   origin is now rotation about the image's center),
> 	3) Translate the origin to the center of the new image.
> 
> You can build these three transforms (it would take me a few tries to
> get the translations right; see Y axis, above) and combine them into a
> single transform (it would take me a few tries to get the order right;
> matrix multiplication is not commutative but at least you know that the
> rotation step is in the middle), and then apply the combined super-
> transform to your image.
>
Good advice. Thanks. I'll look at that tomorrow.
 

-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#31895

Frome.d.programmer@gmail.com
Date2015-06-30 12:07 -0700
Message-ID<228707c4-33ce-4901-9636-97e08cf6ff84@googlegroups.com>
In reply to#31890
On Tuesday, June 30, 2015 at 12:56:43 PM UTC-4, Martin Gregorie wrote:
> Thanks to help from Knute about five 11 months ago I was able to create 
> JLabel subclasses that could display vertically aligned text, e.g.
> 
>    N
>    a
>    m
>    e
> 
> by using HTML text, e.g. "<html>N<br>a<br>m<br>e</html>" This works well, 
> except that some of the longer names create very tall instances that use 
> up more screen than I can really spade (the row of names is near the top 
> of a matrix which has 50+ lines below it, so it would be nice to avoid as 
> much scrolling up and down as possible. 
> 
> Having noticed that most Monospaced characters are just over half as wide 
> as they are high, I'm again thinking about somehow standing the character 
> string on end by rotating it through 90 degrees. I'm successfully 
> creating a JPG image containing black 10 pt Monospaced text on a 
> LIGHT_GRAY background within a minimal window (20 pixels high and 
> s.length() * (fontsize * 7 / 10) wide, whenever I try to rotate it, all 
> I'm getting is a solid black image thats rotated so its longest dimension 
> is now vertical. 
> 
> The code looks like this:
> 
>    BufferedImage im = new BufferedImage(width,
>                                         height,
>                                         BufferedImage.TYPE_INT_RGB);
> 
>    // image created in im
> 
>    BufferedImage om = new BufferedImage(height,
>                                         width,
>                                         BufferedImage.TYPE_INT_RGB);
>    AffineTransform at = new AffineTransform();
>    at.setToQuadrantRotation(-1);
>    AffineTransformOp aop = new AffineTransformOp(at,
>                                AffineTransformOp.TYPE_BILINEAR);
>    aop.filter(im, om);
> 
> I've also tried setting the AffineTransformOp to TYPE_BICUBIC but that 
> also gave a black rectangle.
> 
> I'm obviously doing something stupid or have missed out a vital step, but 
> what?
> 
> 
> -- 
> martin@   | Martin Gregorie
> gregorie. | Essex, UK
> org       |

Are you trying to rotate text or an image?
Which direction is the original?  Which direction did you need it to face after rotating?
To rotate an image I just create a new AffineTransform, scale it, rotate it, and pass it into my drawImage method.
If it's a perfect square the rotate method should be easy, just pass in the Math.toRadians(drawRotationAngle).
If it's a rectangle, not a square, and you want to turn it 90 degrees and squish it to fit the same space you need to calculate a new x/y.

[toc] | [prev] | [next] | [standalone]


#31899

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2015-06-30 20:18 +0000
Message-ID<mmuti0$m87$2@dont-email.me>
In reply to#31890
On Tue, 30 Jun 2015 18:15:41 +0000, Stefan Ram wrote:

> Martin Gregorie <martin@address-in-sig.invalid> writes:
>>s.length() * (fontsize * 7 / 10) wide, whenever I try to rotate it, all
>>I'm getting is a solid black image thats rotated so its longest
>>dimension is now vertical.
> 
>   FWIW, I once wrote a program that rotates letters and has ASCII
>   output:
>
Thanks for that code (snipped to save bandwidth).

I have a transcription running so I can study and modify it to work with 
images rather than text output.

It seems to be working, though it displays 35880 lines of text (2.8MB) as 
it slowly builds the rotated A line by line. I think I need to check it 
over to see why its doing that, as a particular part-built version of the 
A is output many times in the course of assembling the nest 'scan line'.



-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#31902

FromJeff Higgins <jeff@invalid.invalid>
Date2015-06-30 19:04 -0400
Message-ID<mmv7cc$l2$1@dont-email.me>
In reply to#31890
On 06/30/2015 12:55 PM, Martin Gregorie wrote:

Not real pretty but...
<http://www.rgagnon.com/javadetails/java-0259.html>

package scratch;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;

public class DrawVerticalText extends JPanel {
     @Override
     public void paint(Graphics g) {
         Graphics2D g2 = (Graphics2D) g;
         String s = "Vertical text";
         int x=10;
         int y=10;
         int v;

         v=g.getFontMetrics(getFont()).getHeight()+1;
         System.out.println(v);
         int j =0;
         int k= s.length();
         while(j < k+1) {
           if (j == k)
              g.drawString(s.substring(j),x, y+(j*v));
           else
              g.drawString(s.substring(j,j+1),x, y+(j*v));
           j++;
           }
         }


     public static void main(String[] args) {
         JFrame frame = new JFrame();
         frame.setTitle("Draw Vertical Text Demo");
         frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
         frame.add(new DrawVerticalText());
         frame.pack();
         frame.setSize(200, 300);
         frame.setVisible(true);
     }
}

[toc] | [prev] | [next] | [standalone]


#31903

FromKnute Johnson <nospam@rabbitbrush.frazmtn.com>
Date2015-06-30 16:36 -0700
Message-ID<mmv93r$6j9$1@dont-email.me>
In reply to#31902
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class test4 extends JComponent {
     private final String message = "VERTICAL TEXT";
     private final int width = 20;
     private final int height = 220;

     public test4() {
         setFont(new Font("Monospaced",Font.BOLD,16));
         setPreferredSize(new Dimension(width,height));
     }

     public void paintComponent(Graphics g2d) {
         Graphics2D g = (Graphics2D)g2d;
         g.setColor(Color.BLACK);
         g.fillRect(0,0,width,height);
         g.setColor(Color.WHITE);
         char[] chars = message.toCharArray();
         FontMetrics metrics = g.getFontMetrics();
         double charHeight = metrics.getHeight() * 0.7;
         g.translate(
          (width - metrics.charWidth(' '))/2.0,
          (height - charHeight * chars.length)/2.0 + charHeight);
         for (int i=0; i<chars.length; i++) {
             g.drawChars(chars,i,1,0,0);
             g.translate(0,charHeight);
         }
     }

     public static void main(String... args) {
         EventQueue.invokeLater(() -> {
             JFrame f = new JFrame();
             f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
             f.add(new test4(),BorderLayout.CENTER);
             f.pack();
             f.setVisible(true);
         });
     }
}

[toc] | [prev] | [next] | [standalone]


#31905

FromJeff Higgins <jeff@invalid.invalid>
Date2015-06-30 20:17 -0400
Message-ID<mmvbm5$fmi$1@dont-email.me>
In reply to#31903
On 06/30/2015 07:36 PM, Knute Johnson wrote:

I changed the all caps to mixed case just to see.
Yep, pretty vertical text is hard.

> import java.awt.*;
> import java.awt.event.*;
> import javax.swing.*;
>
> public class test4 extends JComponent {
>      private final String message = "VERTICAL TEXT";
>      private final int width = 20;
>      private final int height = 220;
>
>      public test4() {
>          setFont(new Font("Monospaced",Font.BOLD,16));
>          setPreferredSize(new Dimension(width,height));
>      }
>
>      public void paintComponent(Graphics g2d) {
>          Graphics2D g = (Graphics2D)g2d;
>          g.setColor(Color.BLACK);
>          g.fillRect(0,0,width,height);
>          g.setColor(Color.WHITE);
>          char[] chars = message.toCharArray();
>          FontMetrics metrics = g.getFontMetrics();
>          double charHeight = metrics.getHeight() * 0.7;
>          g.translate(
>           (width - metrics.charWidth(' '))/2.0,
>           (height - charHeight * chars.length)/2.0 + charHeight);
>          for (int i=0; i<chars.length; i++) {
>              g.drawChars(chars,i,1,0,0);
>              g.translate(0,charHeight);
>          }
>      }
>
>      public static void main(String... args) {
>          EventQueue.invokeLater(() -> {
>              JFrame f = new JFrame();
>              f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
>              f.add(new test4(),BorderLayout.CENTER);
>              f.pack();
>              f.setVisible(true);
>          });
>      }
> }
>
>

[toc] | [prev] | [next] | [standalone]


#31904

FromJeff Higgins <jeff@invalid.invalid>
Date2015-06-30 20:09 -0400
Message-ID<mmvb6q$egh$1@dont-email.me>
In reply to#31902
On 06/30/2015 07:04 PM, Jeff Higgins wrote:
> On 06/30/2015 12:55 PM, Martin Gregorie wrote:
>
Another interesting idea - haven't tried it.
VerticalLabelUI.java
VerticalTableHeaderCellRenderer.java
<https://java.net/projects/snat/sources/reposit/show/src/table?rev=69>

[toc] | [prev] | [next] | [standalone]


#31907

Frome.d.programmer@gmail.com
Date2015-07-01 06:06 -0700
Message-ID<31e57656-27e3-46a4-abbd-a793c463adba@googlegroups.com>
In reply to#31902
On Tuesday, June 30, 2015 at 7:07:21 PM UTC-4, Jeff Higgins wrote:
> On 06/30/2015 12:55 PM, Martin Gregorie wrote:
> 
> Not real pretty but...
> <http://www.rgagnon.com/javadetails/java-0259.html>
> 
> package scratch;
> 
> import javax.swing.*;
> import java.awt.*;
> import java.awt.geom.AffineTransform;
> 
> public class DrawVerticalText extends JPanel {
>      @Override
>      public void paint(Graphics g) {
>          Graphics2D g2 = (Graphics2D) g;
>          String s = "Vertical text";
>          int x=10;
>          int y=10;
>          int v;
> 
>          v=g.getFontMetrics(getFont()).getHeight()+1;
>          System.out.println(v);
>          int j =0;
>          int k= s.length();
>          while(j < k+1) {
>            if (j == k)
>               g.drawString(s.substring(j),x, y+(j*v));
>            else
>               g.drawString(s.substring(j,j+1),x, y+(j*v));
>            j++;
>            }
>          }
> 
> 
>      public static void main(String[] args) {
>          JFrame frame = new JFrame();
>          frame.setTitle("Draw Vertical Text Demo");
>          frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
>          frame.add(new DrawVerticalText());
>          frame.pack();
>          frame.setSize(200, 300);
>          frame.setVisible(true);
>      }
> }

That doesn't look pretty, though it's using my default font, which is "family=Dialog,name=Dialog,style=plain,size=12".
It doesn't seem to matter in testing your code as is but you should be overriding paintComponent not paint.  That does look prettier if we set a fixed width font.

import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class TestRotatedText extends JPanel {

     @Override
     public void paintComponent(final Graphics g) {
          final Graphics2D g2 = (Graphics2D) g;
          final String s = "Vertical text";
          final int x = 10;
          final int y = 10;
          int v;
          g2.setFont(new Font("Lucida Sans TypeWriter", Font.PLAIN, 12));
          v = g2.getFontMetrics(g2.getFont()).getHeight() + 1;

          int j = 0;
          final int k = s.length();
          while (j < k + 1) {
               if (j == k) {
                    g2.drawString(s.substring(j), x, y + (j * v));
               } else {
                    g2.drawString(s.substring(j, j + 1), x, y + (j * v));
               }
               j++;
          }
     }

     public static void main(final String[] args) {
          final JFrame frame = new JFrame();
          frame.setTitle("Draw Vertical Text Demo");
          frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          frame.add(new TestRotatedText());
          frame.pack();
          frame.setSize(200, 300);
          frame.setVisible(true);
     }
}

It is prettier if you can just turn it.

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class TestRotatedText extends JPanel {

     @Override
     public void paintComponent(final Graphics g) {
          final Graphics2D g2 = (Graphics2D) g;
          final String s = "Vertical text";
          int charHeight;
          g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
          g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
          g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
          g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
          g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
          g2.setFont(new Font("Lucida Sans TypeWriter", Font.PLAIN, 12));
          final Font theFont = g2.getFont();
          final FontMetrics fm = g2.getFontMetrics(theFont);
          charHeight = fm.getHeight();
          // Create a rotation transformation for the font.
          final AffineTransform fontAT = new AffineTransform();
          fontAT.rotate(-Math.PI / 2.0);
          final Font theDerivedFont = theFont.deriveFont(fontAT);
          // set the derived font in the Graphics2D context
          g2.setFont(theDerivedFont);
          g2.drawString(s, charHeight, fm.stringWidth(s) + 5);
     }

     public static void main(final String[] args) {
          final JFrame frame = new JFrame();
          frame.setTitle("Draw Vertical Text Demo");
          frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
          frame.add(new TestRotatedText());
          frame.pack();
          frame.setSize(200, 300);
          frame.setVisible(true);
     }
}

[toc] | [prev] | [next] | [standalone]


#31909

FromFredK <fred.l.kleinschmidt@gmail.com>
Date2015-07-01 10:57 -0700
Message-ID<028164e2-9cba-4ba3-ad34-0cf46ae7210b@googlegroups.com>
In reply to#31907
On Wednesday, July 1, 2015 at 6:06:43 AM UTC-7, e.d.pro...@gmail.com wrote:
> On Tuesday, June 30, 2015 at 7:07:21 PM UTC-4, Jeff Higgins wrote:
> > On 06/30/2015 12:55 PM, Martin Gregorie wrote:
> > 
> > Not real pretty but...
> > <http://www.rgagnon.com/javadetails/java-0259.html>
> > 
> > package scratch;
> > 
> > import javax.swing.*;
> > import java.awt.*;
> > import java.awt.geom.AffineTransform;
> > 
> > public class DrawVerticalText extends JPanel {
> >      @Override
> >      public void paint(Graphics g) {
> >          Graphics2D g2 = (Graphics2D) g;
> >          String s = "Vertical text";
> >          int x=10;
> >          int y=10;
> >          int v;
> > 
> >          v=g.getFontMetrics(getFont()).getHeight()+1;
> >          System.out.println(v);
> >          int j =0;
> >          int k= s.length();
> >          while(j < k+1) {
> >            if (j == k)
> >               g.drawString(s.substring(j),x, y+(j*v));
> >            else
> >               g.drawString(s.substring(j,j+1),x, y+(j*v));
> >            j++;
> >            }
> >          }
> > 
> > 
> >      public static void main(String[] args) {
> >          JFrame frame = new JFrame();
> >          frame.setTitle("Draw Vertical Text Demo");
> >          frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
> >          frame.add(new DrawVerticalText());
> >          frame.pack();
> >          frame.setSize(200, 300);
> >          frame.setVisible(true);
> >      }
> > }
> 
> That doesn't look pretty, though it's using my default font, which is "family=Dialog,name=Dialog,style=plain,size=12".
> It doesn't seem to matter in testing your code as is but you should be overriding paintComponent not paint.  That does look prettier if we set a fixed width font.
> 
> import java.awt.Font;
> import java.awt.Graphics;
> import java.awt.Graphics2D;
> 
> import javax.swing.JFrame;
> import javax.swing.JPanel;
> import javax.swing.WindowConstants;
> 
> public class TestRotatedText extends JPanel {
> 
>      @Override
>      public void paintComponent(final Graphics g) {
>           final Graphics2D g2 = (Graphics2D) g;
>           final String s = "Vertical text";
>           final int x = 10;
>           final int y = 10;
>           int v;
>           g2.setFont(new Font("Lucida Sans TypeWriter", Font.PLAIN, 12));
>           v = g2.getFontMetrics(g2.getFont()).getHeight() + 1;
> 
>           int j = 0;
>           final int k = s.length();
>           while (j < k + 1) {
>                if (j == k) {
>                     g2.drawString(s.substring(j), x, y + (j * v));
>                } else {
>                     g2.drawString(s.substring(j, j + 1), x, y + (j * v));
>                }
>                j++;
>           }
>      }
> 
>      public static void main(final String[] args) {
>           final JFrame frame = new JFrame();
>           frame.setTitle("Draw Vertical Text Demo");
>           frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
>           frame.add(new TestRotatedText());
>           frame.pack();
>           frame.setSize(200, 300);
>           frame.setVisible(true);
>      }
> }
> 
> It is prettier if you can just turn it.
> 
> import java.awt.Font;
> import java.awt.FontMetrics;
> import java.awt.Graphics;
> import java.awt.Graphics2D;
> import java.awt.RenderingHints;
> import java.awt.geom.AffineTransform;
> 
> import javax.swing.JFrame;
> import javax.swing.JPanel;
> import javax.swing.WindowConstants;
> 
> public class TestRotatedText extends JPanel {
> 
>      @Override
>      public void paintComponent(final Graphics g) {
>           final Graphics2D g2 = (Graphics2D) g;
>           final String s = "Vertical text";
>           int charHeight;
>           g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
>           g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
>           g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
>           g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
>           g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
>           g2.setFont(new Font("Lucida Sans TypeWriter", Font.PLAIN, 12));
>           final Font theFont = g2.getFont();
>           final FontMetrics fm = g2.getFontMetrics(theFont);
>           charHeight = fm.getHeight();
>           // Create a rotation transformation for the font.
>           final AffineTransform fontAT = new AffineTransform();
>           fontAT.rotate(-Math.PI / 2.0);
>           final Font theDerivedFont = theFont.deriveFont(fontAT);
>           // set the derived font in the Graphics2D context
>           g2.setFont(theDerivedFont);
>           g2.drawString(s, charHeight, fm.stringWidth(s) + 5);
>      }
> 
>      public static void main(final String[] args) {
>           final JFrame frame = new JFrame();
>           frame.setTitle("Draw Vertical Text Demo");
>           frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
>           frame.add(new TestRotatedText());
>           frame.pack();
>           frame.setSize(200, 300);
>           frame.setVisible(true);
>      }
> }


Just extend JLabel. Note the horizontal and vertical alignments are kept relative to the text, so "vertical" refers to the height of the text, not the height of the widget.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

public class VerticalLabel extends JLabel {

   Insets insets;

   public VerticalLabel( String string ) {
      super( string );
   }

   @Override
   public void paintComponent( Graphics g ) {
      insets = getInsets();
      Dimension size = getSize();
      String text = getText();
      int x = 0;
      int y = 0;
      int halign = getHorizontalAlignment();
      int valign = getVerticalAlignment();

      FontMetrics metrics = getFontMetrics( getFont() );
      int ascent = metrics.getAscent();
      int descent = metrics.getDescent();
      setVerticalAlignment( SwingConstants.BOTTOM );
      setHorizontalAlignment( SwingConstants.CENTER );
      int line = metrics.stringWidth( text );
      switch (halign) {
         case SwingConstants.LEFT:
         case SwingConstants.LEADING:
            y = size.height - insets.bottom;
            break;
         case SwingConstants.CENTER:
            y = (insets.top + size.height - insets.bottom + line) / 2;
            break;
         default:
            y = insets.top + line;
            break;

      }
      switch (valign) {
         case SwingConstants.TOP:
            x = insets.left + ascent;
            break;
         case SwingConstants.CENTER:
            x = (insets.left + size.width - insets.right - ascent) / 2;
            break;
         default:
            x = size.width - insets.right - descent;
            break;
      }

      ((Graphics2D)g).rotate( Math.toRadians( -90 ), x, y );
      ((Graphics2D)g).drawString( text, x, y );
      ((Graphics2D)g).rotate( Math.toRadians( 90 ), x, y );

   }

   @Override
   public Dimension getPreferredSize() {
      Dimension d = super.getPreferredSize();
      int temp = d.height;
      d.height = d.width;
      d.width = temp;
      return d;
   }
}

-- 
Fred K

[toc] | [prev] | [next] | [standalone]


#31912

FromJeff Higgins <jeff@invalid.invalid>
Date2015-07-01 18:13 -0400
Message-ID<mn1ooh$pdu$1@dont-email.me>
In reply to#31907
On 07/01/2015 09:06 AM, e.d.programmer@gmail.com wrote:

>
> It is prettier if you can just turn it.

Yep, pretty, but then from the OP:

 > Thanks to help from Knute about five 11 months ago I was able to
 > create
 > JLabel subclasses that could display vertically aligned text, e.g.

 >    N
 >    a
 >    m
 >    e

[toc] | [prev] | [next] | [standalone]


#32173

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-07-27 22:28 -0400
Message-ID<mp6pbo$19j$4@speranza.aioe.org>
In reply to#31907
On 7/1/2015 9:06 AM, e.d.programmer@gmail.com wrote:
> On Tuesday, June 30, 2015 at 7:07:21 PM UTC-4, Jeff Higgins wrote:

>>       public static void main(String[] args) {
>>           JFrame frame = new JFrame();
>>           frame.setTitle("Draw Vertical Text Demo");
>>           frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
>>           frame.add(new DrawVerticalText());
>>           frame.pack();
>>           frame.setSize(200, 300);
>>           frame.setVisible(true);
>>       }
>> }

>       public static void main(final String[] args) {
>            final JFrame frame = new JFrame();
>            frame.setTitle("Draw Vertical Text Demo");
>            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
>            frame.add(new TestRotatedText());
>            frame.pack();
>            frame.setSize(200, 300);
>            frame.setVisible(true);
>       }
> }

And consider moving this stuff from main thread to the event thread,
since that is how it is supposed to be done.

Arne


[toc] | [prev] | [next] | [standalone]


#32180

Frome.d.programmer@gmail.com
Date2015-07-28 04:58 -0700
Message-ID<4205e406-2568-4c74-a948-8fb425075b51@googlegroups.com>
In reply to#32173
On Monday, July 27, 2015 at 10:28:21 PM UTC-4, Arne Vajhøj wrote:
> And consider moving this stuff from main thread to the event thread,
> since that is how it is supposed to be done.
> 
> Arne

I never put that stuff on the main thread.  I was just modifying someone else's sample.

[toc] | [prev] | [next] | [standalone]


#32186

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-07-28 18:58 -0400
Message-ID<mp91eg$6b7$2@speranza.aioe.org>
In reply to#32180
On 7/28/2015 7:58 AM, e.d.programmer@gmail.com wrote:
> On Monday, July 27, 2015 at 10:28:21 PM UTC-4, Arne Vajhøj wrote:
>> And consider moving this stuff from main thread to the event thread,
>> since that is how it is supposed to be done.
>
> I never put that stuff on the main thread.  I was just modifying someone else's sample.

Yes.

And you chose not to modify that part.

So I made a note so that readers do not get the wrong impression
about what they should do.

Arne

[toc] | [prev] | [next] | [standalone]


#32194

Frome.d.programmer@gmail.com
Date2015-07-29 05:35 -0700
Message-ID<ef946ad1-468d-4b02-bc0e-eeeed0aa5d55@googlegroups.com>
In reply to#32186
On Tuesday, July 28, 2015 at 6:58:31 PM UTC-4, Arne Vajhøj wrote:
> Yes.
> 
> And you chose not to modify that part.
> 
> So I made a note so that readers do not get the wrong impression
> about what they should do.
> 
> Arne

Disclaimer: That is not production code.  That was a sample modified to solve a specific problem.  Any reader who thinks you should create a JFrame and make it visible in the main method should probably take a Java class.
I didn't modify that part because it wasn't relevant to solving the problem.  If it were a final program to put into production I would personally change a lot more than moving the JFrame to an event thread.
The simplest change to fix that one issue would be to write all main threads with GUI like this.
     public static void main(final String[] args) {
          EventQueue.invokeLater(new Runnable() {

               @Override
               public void run() {
               // test program here
               }
          });
     }
Personally I don't use JFrame.  I like to write flexible applications.  I like making a window with a button that can open a second window and disable the first window until you close the second window.  I couldn't find an easy way to do that with a JFrame, so I made all windows extend JDialog, so I can make them DOCUMENT_MODAL and pass one into another as it's owner.  I also don't use EXIT_ON_CLOSE.  I set DO_NOTHING_ON_CLOSE, then assign a WindowListener linked to a KeyStroke on the InputMap that can allow them to also close with an F# key and prompt when they try to close and do some cleanup ie identify if a control is modified and prompt them to save.

So anyway, don't nitpick a sample.  If you want to make sure readers who are new to Java don't get the idea they should do something everyone ought to know not to do, you might as well point those readers to the Java tutorial.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web