Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Java (http://www.velocityreviews.com/forums/f30-java.html)
-   -   Why does AffineTransform not work on JTextPane? (http://www.velocityreviews.com/forums/t363556-why-does-affinetransform-not-work-on-jtextpane.html)

fiziwig 08-10-2006 05:20 PM

Why does AffineTransform not work on JTextPane?
 
I can rotate every other type of component I've tried, but when I
rotate a JTextPane by 90 or 180 degrees (which I REALLY need for my
customer's application) The clipping and bordering get all messed up
and I'm at my wit's end trying to make it work.

Am I doing something wrong, or is there a Java bug in applying a
transform to a JTextPane? The same basic code works on a JLabel, why
won't it work on a JTextPane?

Any ideas or suggestions would be deeply appreciated.

OR any ideas for a different way to display STYLED text (font, size,
color, bold, italic on a character-by-character basis) at a 90 or 180
degree rotation. It doesn't have to be editable when rotated, but it
does need to be editable when upright, otherwise I'd just use HTML in a
JLabel.

Thanks,

--gary

Compilable example:


import javax.swing.*;
import javax.swing.text.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;

public class Rotate extends JPanel {

private TextPanel textPane;
private JLayeredPane parent;

public Rotate() {

setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
JToolBar toolBar = buildToolbar();
add(toolBar);

parent = new JLayeredPane();
add(parent);
parent.setBackground( Color.gray);
parent.setPreferredSize(new Dimension(640, 480));

// Create a text pane.

textPane = new TextPanel();
StyledDocument doc = textPane.getStyledDocument();
try {
doc.insertString(doc.getLength(), "This is some sample
text.\nIt can be Rotated.", null);
}
catch (BadLocationException ble) {
System.err.println("Couldn't insert initial text into text
pane.");
}
Border myBorder = BorderFactory.createLineBorder( Color.red );
textPane.setBorder(myBorder);
parent.setOpaque(true);
parent.add(textPane);
textPane.setDefaultBounds(120, 120, 240, 120);
}
private JToolBar buildToolbar() {

JToolBar toolBar = new JToolBar();
toolBar.setRollover( true );
toolBar.setFloatable( false );
JButton rotateButton = new JButton("Rotate");
rotateButton.setToolTipText( "Rotate text editing pane" );
rotateButton.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
textPane.setRotation(textPane.getRotation()+1);
}
});
toolBar.add( rotateButton );
return toolBar;
}
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);

//Create and set up the window.
JFrame frame = new JFrame("Rotate");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS E);

//Create and set up the content pane.
JComponent newContentPane = new Rotate();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);

//Display the window.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}

}

class TextPanel extends JTextPane {

// implements rotation for a JTextPane

private int rotation;
private int tx, ty;
private int wide, high;

// valid rotation values are:
// 0 = no rotation
// 1 = rotation 90 degree clockwise
// 2 = rotation 180 degrees
// 3 = rotation 90 degrees counterclockwise

TextPanel() {
super();
rotation = 0;
tx = 0;
ty = 0;
}
public void setDefaultBounds( int x, int y, int width, int height)
{
high = height;
wide = width;
super.setBounds(x,y,width,height);
}
public void setRotation( int newRotation ) {
rotation = newRotation % 4;

if ((rotation%2)==0) {
setSize(wide,high);
} else {
setSize(high,wide);
}
switch (rotation) {
case 0 : tx = 0; ty = 0; break;
case 1 : tx = 1; ty = 0; break;
case 2 : tx = 1; ty = 1; break;
case 3 : tx = 0; ty = 1; break;
}
repaint();
}
public int getRotation() { return rotation; }

public void paintComponent(Graphics g) {

Graphics2D g2 = (Graphics2D) g;
double angle = rotation * Math.PI/2;
AffineTransform tr = g2.getTransform();
int h,w;
if ((rotation%2) == 0) {
w = wide;
h = high;
} else {
h = wide;
w = high;
}

tr.setToTranslation(getWidth()*tx,getHeight()*ty);
tr.rotate(angle);
g2.setTransform(tr); // <----- comment this line out to see
correct borders
super.paintComponent(g2);
}
}


Oliver Wong 08-10-2006 06:29 PM

Re: Why does AffineTransform not work on JTextPane?
 

"fiziwig" <fiziwig@yahoo.com> wrote in message
news:1155230449.689102.242070@m79g2000cwm.googlegr oups.com...
>I can rotate every other type of component I've tried, but when I
> rotate a JTextPane by 90 or 180 degrees (which I REALLY need for my
> customer's application) The clipping and bordering get all messed up
> and I'm at my wit's end trying to make it work.
>
> Am I doing something wrong, or is there a Java bug in applying a
> transform to a JTextPane? The same basic code works on a JLabel, why
> won't it work on a JTextPane?
>
> Any ideas or suggestions would be deeply appreciated.
>
> OR any ideas for a different way to display STYLED text (font, size,
> color, bold, italic on a character-by-character basis) at a 90 or 180
> degree rotation. It doesn't have to be editable when rotated, but it
> does need to be editable when upright, otherwise I'd just use HTML in a
> JLabel.


How about using a JTextPane for editing, and when editing is done, copy
the contents and put it into a JLabel, and rotate the JLabel?

- Oliver


fiziwig 08-10-2006 06:44 PM

Re: Why does AffineTransform not work on JTextPane?
 

Oliver Wong wrote:
> "fiziwig" <fiziwig@yahoo.com> wrote in message


<snip>

> > OR any ideas for a different way to display STYLED text (font, size,
> > color, bold, italic on a character-by-character basis) at a 90 or 180
> > degree rotation. It doesn't have to be editable when rotated, but it
> > does need to be editable when upright, otherwise I'd just use HTML in a
> > JLabel.

>
> How about using a JTextPane for editing, and when editing is done, copy
> the contents and put it into a JLabel, and rotate the JLabel?
>
> - Oliver


That might work. The problem is then I have to go through the text
character by character pulling out the attributes (font, size, color,
bold, italic,...) and turning those into HTML tags so that they will
display properly in the JLabel. Then when the user selects the text for
editing again I have to turn around and parse out all the HTML tags and
build it back into a styled document.

This would be soooo easy in C++/Windows, but Java makes the hard things
easy by making the easy things hard, by keeping some very important
things hidden and inaccessable. That's great most of the time, but it's
a major pain in the neck at other times. It's like trying to build a
geodesic dome with Lincoln logs. The Java Lincoln logs are great as
long as you're building their kind of rectalinear log-cabin-type stuff,
but to build anything unconventional, like round or octagonal, you're
flat out of luck.

--gary


Oliver Wong 08-10-2006 06:54 PM

Re: Why does AffineTransform not work on JTextPane?
 

"fiziwig" <fiziwig@yahoo.com> wrote in message
news:1155235460.892436.215590@p79g2000cwp.googlegr oups.com...
>
> Oliver Wong wrote:
>> "fiziwig" <fiziwig@yahoo.com> wrote in message

>
> <snip>
>
>> > OR any ideas for a different way to display STYLED text (font, size,
>> > color, bold, italic on a character-by-character basis) at a 90 or 180
>> > degree rotation. It doesn't have to be editable when rotated, but it
>> > does need to be editable when upright, otherwise I'd just use HTML in a
>> > JLabel.

>>
>> How about using a JTextPane for editing, and when editing is done,
>> copy
>> the contents and put it into a JLabel, and rotate the JLabel?
>>

>
> That might work. The problem is then I have to go through the text
> character by character pulling out the attributes (font, size, color,
> bold, italic,...) and turning those into HTML tags so that they will
> display properly in the JLabel. Then when the user selects the text for
> editing again I have to turn around and parse out all the HTML tags and
> build it back into a styled document.


Or you could have a central "model" object which semantically preserves
all the information you need in your document, and generate HTML like views
for the Label, and the character-style like view and editor for the
JTextPane.

Another thing you could try is, once the user has finished editing
everything, taking a screen capture of the JTextPane, and then rotating that
image, and displaying it.

- Oliver


fiziwig 08-10-2006 07:04 PM

Re: Why does AffineTransform not work on JTextPane?
 

Oliver Wong wrote:
> "fiziwig" <fiziwig@yahoo.com> wrote in message
> news:1155235460.892436.215590@p79g2000cwp.googlegr oups.com...
> >
> > Oliver Wong wrote:
> >> "fiziwig" <fiziwig@yahoo.com> wrote in message

> >


<snip>

>
> Another thing you could try is, once the user has finished editing
> everything, taking a screen capture of the JTextPane, and then rotating that
> image, and displaying it.
>
> - Oliver


The screen cap idea is a good one. That would be perfectly suitable.
This is a page layout program for a customer who is a printer and he
needs to be able to turn blocks of text on their side or upside down in
doing multi-page layouts on a single very large sheet of paper. There
can be literally dozens of separate JTextPanes in a single document.

I'll look into the screen cap approach. If I can figure out how to do a
screen cap, that is. ;-)

Thanks,

--gary


Oliver Wong 08-10-2006 07:58 PM

Re: Why does AffineTransform not work on JTextPane?
 
"fiziwig" <fiziwig@yahoo.com> wrote in message
news:1155236644.612852.52050@i42g2000cwa.googlegro ups.com...
>
> I'll look into the screen cap approach. If I can figure out how to do a
> screen cap, that is. ;-)


See
http://java.sun.com/products/java-me...tml#displaybmp

- Oliver


fiziwig 08-10-2006 08:52 PM

Re: Why does AffineTransform not work on JTextPane?
 

Oliver Wong wrote:
> "fiziwig" <fiziwig@yahoo.com> wrote in message
> news:1155236644.612852.52050@i42g2000cwa.googlegro ups.com...
> >
> > I'll look into the screen cap approach. If I can figure out how to do a
> > screen cap, that is. ;-)

>
> See
> http://java.sun.com/products/java-me...tml#displaybmp
>
> - Oliver


Thanks for all your help. After days and days of pulling my hair out,
the rotation finally works perfectly. Here's how I ended up doing it:

class TextPanel extends JTextPane {

// implements rotation for a JTextPane

private int rotation;
private int tx, ty;
private int wide, high;
private BufferedImage renderedText = null;

// valid rotation values are:
// 0 = no rotation
// 1 = rotation 90 degree clockwise
// 2 = rotation 180 degrees
// 3 = rotation 90 degrees counterclockwise

TextPanel() {
super();
rotation = 0;
tx = 0;
ty = 0;
}
public void setDefaultBounds( int x, int y, int width, int height)
{
high = height;
wide = width;
super.setBounds(x,y,width,height);
}
public void setRotation( int newRotation ) {

newRotation = newRotation % 4;
if ( rotation != newRotation ) {
switch (newRotation) {
case 0 : tx = 0; ty = 0; break;
case 1 : tx = 1; ty = 0; break;
case 2 : tx = 1; ty = 1; break;
case 3 : tx = 0; ty = 1; break;
}
if ( newRotation != 0 ) {
if ( renderedText==null) {
rotation = 0; // so that text is actually rendered
renderedText = new BufferedImage(wide, high,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2D = renderedText.createGraphics();
paint( g2D );
}
}
rotation = newRotation; // so the repaint will paint the
rendered image
if ((rotation%2)==0) {
setSize(wide,high);
} else {
setSize(high,wide);
}

repaint();
}
}
public int getRotation() { return rotation; }

public void paintComponent(Graphics g) {

if ( rotation == 0 ) {
super.paintComponent(g);
return;
}
Graphics2D g2 = (Graphics2D) g;
double angle = rotation * Math.PI/2;
AffineTransform tr = g2.getTransform();
if (rotation==2) {
tr.setToTranslation(wide*tx,high*ty);
} else {
tr.setToTranslation(high*tx,wide*ty);
}
tr.rotate(angle);
g2.drawImage(renderedText, tr, this);
}
}

--gary


Thomas Weidenfeller 08-11-2006 08:42 AM

Re: Why does AffineTransform not work on JTextPane?
 
fiziwig wrote:

> public void paintComponent(Graphics g) {


Override paint(), not paintComponent() but before you do so, familiarize
yourself with the way paint() in Swing works. There is a TSC painting
article about this.

/Thomas
--
The comp.lang.java.gui FAQ:
ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/...g/java/gui/faq
http://www.uni-giessen.de/faq/archiv....java.gui.faq/

Alex Hunsley 08-12-2006 02:14 AM

Re: Why does AffineTransform not work on JTextPane?
 
Thomas Weidenfeller wrote:
> fiziwig wrote:
>
>> public void paintComponent(Graphics g) {

>
> Override paint(), not paintComponent() but before you do so, familiarize
> yourself with the way paint() in Swing works. There is a TSC painting
> article about this.


Why do you suggest doing this?


jmcgill 08-12-2006 02:25 PM

Re: Why does AffineTransform not work on JTextPane?
 
Alex Hunsley wrote:
> Thomas Weidenfeller wrote:
>> fiziwig wrote:
>>
>>> public void paintComponent(Graphics g) {

>>
>> Override paint(), not paintComponent() but before you do so,
>> familiarize yourself with the way paint() in Swing works. There is a
>> TSC painting article about this.

>
> Why do you suggest doing this?
>


I'm not convinced that's exactly what this article is saying. Maybe the
OP has another TSC painting article in mind, or maybe I'm not reading
this well.

http://java.sun.com/products/jfc/tsc/articles/painting/



All times are GMT. The time now is 11:58 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.