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_CLOSE);
//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);
}
}