943,668 Members | Top Members by Rank

Ad:
  • Java Discussion Thread
  • Marked Solved
  • Views: 3939
  • Java RSS
Sep 13th, 2008
0

Having problems rotating Shapes in JPanel

Expand Post »
This is a simplified version of a larger project. I have three JPanels contained in a larger JSplitPane called wholePanel . The top panel and left panel hold labels and buttons, which I have not included here. The lower right panel, called canvasPanel , is where I draw shapes. I'm trying to tilt an oval at an angle and I am successful at doing so. However, a problem occurs when I resize canvasPanel . The oval will jump if you drag the Pane dividers to resize. I believe that what is occurring is that the oval is realigning itself sometimes with respect to the upper left corner of wholePanel and sometimes with respect to the upper left of canvasPanel. So it has an annoying jump. I want it to always align itself with respect to canvasPanel , not wholePanel . This seems to happen because of the AffineTransform, but I don't know why or how to fix it.

My second problem is that sometimes canvasPanel does not paint until I resize it, leaving a dull gray panel with no background color and no shape. I want it to paint without the user having to do anything. Thank you. Code is below.

JAVA Syntax (Toggle Plain Text)
  1. package ColorForms;
  2.  
  3. import javax.swing.border.*;
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import java.awt.geom.*;
  7. import java.io.*;
  8. import javax.swing.*;
  9. import java.util.*;
  10. import java.lang.*;
  11.  
  12.  
  13.  
  14. public class ColorForms extends JFrame
  15. {
  16. LeftPanel leftPanel;
  17. TopPanel topPanel;
  18. CanvasPanel canvasPanel;
  19. JSplitPane wholePanel, bottomPanel;
  20.  
  21. public static void main (String args[])
  22. {
  23. ColorForms cf = new ColorForms ();
  24. }
  25.  
  26.  
  27. public ColorForms ()
  28. {
  29. this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
  30. this.setSize (400, 400);
  31. this.setVisible (true);
  32.  
  33. leftPanel = new LeftPanel ();
  34. topPanel = new TopPanel ();
  35. canvasPanel = new CanvasPanel ();
  36.  
  37. bottomPanel = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT, leftPanel, canvasPanel);
  38. bottomPanel.setDividerLocation (50);
  39. wholePanel = new JSplitPane (JSplitPane.VERTICAL_SPLIT, topPanel, bottomPanel);
  40. wholePanel.setDividerLocation (70);
  41.  
  42. this.getContentPane ().add (wholePanel);
  43. }
  44. }
  45.  
  46.  
  47. class LeftPanel extends JPanel
  48. {
  49. public LeftPanel ()
  50. {
  51. }
  52. }
  53.  
  54.  
  55. class TopPanel extends JPanel
  56. {
  57. public TopPanel ()
  58. {
  59.  
  60. }
  61. }
  62.  
  63.  
  64. class CanvasPanel extends JPanel
  65. {
  66. public CanvasPanel ()
  67. {
  68. }
  69.  
  70.  
  71. public void paintComponent (Graphics g)
  72. {
  73. System.out.println ("I am in CanvasPanel repaint.");
  74.  
  75. int ovalCenterX = 100;
  76. int ovalCenterY = 100;
  77. int ovalWidth = 200;
  78. int ovalHeight = 100;
  79. int ovalUpperLeftX = ovalCenterX - ovalWidth / 2;
  80. int ovalUpperLeftY = ovalCenterY - ovalHeight / 2;
  81. double angle = 0.5;
  82.  
  83. super.paintComponent (g);
  84. Graphics2D g2 = (Graphics2D) g;
  85. g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  86. setBackground(Color.GREEN);
  87.  
  88. AffineTransform orig = g2.getTransform();
  89. AffineTransform af = new AffineTransform ();
  90. af.rotate(angle, ovalCenterX, ovalCenterY);
  91. g2.setTransform(af);
  92. g2.setColor (Color.BLACK);
  93. g2.fillOval (ovalUpperLeftX, ovalUpperLeftY, ovalWidth, ovalHeight);
  94. g2.setTransform(orig);
  95. }
  96. }
Featured Poster
Reputation Points: 2614
Solved Threads: 687
Posting Expert
VernonDozier is offline Offline
5,372 posts
since Jan 2008
Sep 13th, 2008
0

Re: Having problems rotating Shapes in JPanel

After running some tests I realized that somehow your transform is jumping between 1-22 on the (result?) matrice--

java Syntax (Toggle Plain Text)
  1. import javax.swing.border.*;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.awt.geom.*;
  5. import java.io.*;
  6. import javax.swing.*;
  7. import java.util.*;
  8. import java.lang.*;
  9.  
  10.  
  11.  
  12. public class ColorForms extends JFrame
  13. {
  14. LeftPanel leftPanel;
  15. TopPanel topPanel;
  16. CanvasPanel canvasPanel;
  17. JSplitPane wholePanel, bottomPanel;
  18.  
  19. public static void main (String args[])
  20. {
  21. ColorForms cf = new ColorForms ();
  22. }
  23.  
  24.  
  25. public ColorForms ()
  26. {
  27. this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
  28. this.setSize (400, 400);
  29. this.setVisible (true);
  30.  
  31. leftPanel = new LeftPanel ();
  32. topPanel = new TopPanel ();
  33. canvasPanel = new CanvasPanel ();
  34.  
  35. bottomPanel = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT, leftPanel, canvasPanel);
  36. bottomPanel.setDividerLocation (50);
  37. wholePanel = new JSplitPane (JSplitPane.VERTICAL_SPLIT, topPanel, bottomPanel);
  38. wholePanel.setDividerLocation (70);
  39.  
  40. this.getContentPane ().add (wholePanel);
  41. }
  42. }
  43.  
  44.  
  45. class LeftPanel extends JPanel
  46. {
  47. public LeftPanel ()
  48. {
  49. }
  50. }
  51.  
  52.  
  53. class TopPanel extends JPanel
  54. {
  55. public TopPanel ()
  56. {
  57.  
  58. }
  59. }
  60.  
  61.  
  62. class CanvasPanel extends JPanel
  63. {
  64. public CanvasPanel ()
  65. {
  66. }
  67.  
  68.  
  69. public void paintComponent (Graphics g)
  70. {
  71. System.out.println (((Graphics2D)g).getTransform());
  72.  
  73. int ovalCenterX = 100;
  74. int ovalCenterY = 100;
  75. int ovalWidth = 200;
  76. int ovalHeight = 100;
  77. int ovalUpperLeftX = ovalCenterX - ovalWidth / 2;
  78. int ovalUpperLeftY = ovalCenterY - ovalHeight / 2;
  79. double angle = 0.5;
  80.  
  81. super.paintComponent (g);
  82. Graphics2D g2 = (Graphics2D) g;
  83. g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  84. setBackground(Color.GREEN);
  85.  
  86. AffineTransform orig = g2.getTransform();
  87. AffineTransform af = new AffineTransform ();
  88. af.rotate(angle, ovalCenterX, ovalCenterY);
  89. g2.setTransform(af);
  90. g2.setColor (Color.BLACK);
  91. g2.fillOval (ovalUpperLeftX, ovalUpperLeftY, ovalWidth, ovalHeight);
  92. g2.setTransform(orig);
  93. // g2.setTransform(af);
  94. }
  95. }

-but I can't say much else with my lack of knowledge in transformations =/
Reputation Points: 392
Solved Threads: 108
Posting Shark
Alex Edwards is offline Offline
971 posts
since Jun 2008
Sep 13th, 2008
0

Re: Having problems rotating Shapes in JPanel

Alex, thanks for looking at it. I'm a little confused about what you meant with this line:

Quote ...
After running some tests I realized that somehow your transform is jumping between 1-22 on the (result?) matrice--
I put in some debugging output and the matrix values are staying the same for me. Maybe we aren't talking about the same thing.

I added a button which causes a repaint to see what that did and the results are interesting. Click the button and the oval appears to draw where I want it to. Drag the PANE resize bars and the oval jumps. It really looks like it is drawing at the proper (x,y) coordinates, but that it's baseline (0, 0) coordinate is changing from the upper left of canvasPanel to the upper left of another panel/pane, but again I don't know why or what to do about it. Here's the updated code with the button.

JAVA Syntax (Toggle Plain Text)
  1. package ColorForms;
  2.  
  3. import javax.swing.border.*;
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import java.awt.geom.*;
  7. import java.io.*;
  8. import javax.swing.*;
  9. import java.util.*;
  10. import java.lang.*;
  11.  
  12.  
  13. public class ColorForms extends JFrame
  14. {
  15. LeftPanel leftPanel;
  16. TopPanel topPanel;
  17. CanvasPanel canvasPanel;
  18. JSplitPane wholePanel, bottomPanel;
  19.  
  20. public static void main (String args[])
  21. {
  22. ColorForms cf = new ColorForms ();
  23. }
  24.  
  25.  
  26. public ColorForms ()
  27. {
  28. this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
  29. this.setSize (400, 400);
  30. this.setVisible (true);
  31.  
  32. leftPanel = new LeftPanel ();
  33. topPanel = new TopPanel (this);
  34. canvasPanel = new CanvasPanel ();
  35.  
  36. bottomPanel = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT, leftPanel, canvasPanel);
  37. bottomPanel.setDividerLocation (50);
  38. wholePanel = new JSplitPane (JSplitPane.VERTICAL_SPLIT, topPanel, bottomPanel);
  39. wholePanel.setDividerLocation (70);
  40.  
  41. this.getContentPane ().add (wholePanel);
  42. }
  43. }
  44.  
  45.  
  46. class LeftPanel extends JPanel
  47. {
  48. public LeftPanel ()
  49. {
  50. }
  51. }
  52.  
  53.  
  54. class TopPanel extends JPanel implements ActionListener
  55. {
  56. JButton repaintButton;
  57. ColorForms cf;
  58.  
  59. public TopPanel (ColorForms cForm)
  60. {
  61. cf = cForm;
  62. repaintButton = new JButton ("Repaint");
  63. repaintButton.addActionListener(this);
  64. add (repaintButton);
  65. }
  66.  
  67. public void actionPerformed(ActionEvent e)
  68. {
  69. cf.canvasPanel.repaint ();
  70. }
  71. }
  72.  
  73.  
  74. class CanvasPanel extends JPanel
  75. {
  76. int timesPainted = 0;
  77.  
  78. public CanvasPanel ()
  79. {
  80. }
  81.  
  82.  
  83. public void paintComponent (Graphics g)
  84. {
  85. timesPainted++;
  86. System.out.print ("I am in CanvasPanel repaint. # of times painted = ");
  87. System.out.println (timesPainted);
  88.  
  89. int ovalCenterX = 100;
  90. int ovalCenterY = 100;
  91. int ovalWidth = 200;
  92. int ovalHeight = 100;
  93. int ovalUpperLeftX = ovalCenterX - ovalWidth / 2;
  94. int ovalUpperLeftY = ovalCenterY - ovalHeight / 2;
  95. double angle = 0.5;
  96.  
  97. super.paintComponent (g);
  98. Graphics2D g2 = (Graphics2D) g;
  99. g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  100. setBackground(Color.GREEN);
  101.  
  102. AffineTransform orig = g2.getTransform();
  103. AffineTransform af = new AffineTransform ();
  104. af.rotate(angle, ovalCenterX, ovalCenterY);
  105. g2.setTransform(af);
  106.  
  107.  
  108. // display AffineTransform attributes
  109. System.out.println (af.getScaleX());
  110. System.out.println (af.getScaleY());
  111. System.out.println (af.getShearX());
  112. System.out.println (af.getShearY());
  113. System.out.println (af.getTranslateX());
  114. System.out.println (af.getTranslateY());
  115.  
  116. g2.setColor (Color.BLACK);
  117. g2.fillOval (ovalUpperLeftX, ovalUpperLeftY, ovalWidth, ovalHeight);
  118. g2.setTransform(orig);
  119. }
  120. }
Featured Poster
Reputation Points: 2614
Solved Threads: 687
Posting Expert
VernonDozier is offline Offline
5,372 posts
since Jan 2008
Sep 14th, 2008
0

Re: Having problems rotating Shapes in JPanel

I've been playing around with this. I added MouseListeners to the top panel and the canvas panel. Like the button, if you click on either, it will redraw in the correct place. I also draw a circle on the canvas that doesn't use a transform and it doesn't do that jump. Finally, when I add a ComponentListener (presently commented out) to the canvas panel and have it repaint when the component is resized, I don't need to click a panel or a button, but it jumps back and forth if you drag by the lower right corner. I'd still like to understand what's going on though. Thanks.

JAVA Syntax (Toggle Plain Text)
  1. package ColorForms;
  2.  
  3. import javax.swing.border.*;
  4. import java.awt.*;
  5. import java.awt.event.*;
  6. import java.awt.geom.*;
  7. import java.io.*;
  8. import javax.swing.*;
  9. import java.util.*;
  10. import java.lang.*;
  11.  
  12.  
  13.  
  14. public class ColorForms extends JFrame // implements ComponentListener
  15. {
  16. LeftPanel leftPanel;
  17. TopPanel topPanel;
  18. CanvasPanel canvasPanel;
  19. JSplitPane wholePanel, bottomPanel;
  20.  
  21. public static void main (String args[])
  22. {
  23. ColorForms cf = new ColorForms ();
  24. }
  25.  
  26.  
  27. public ColorForms ()
  28. {
  29. this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
  30. this.setSize (400, 400);
  31. this.setVisible (true);
  32.  
  33. leftPanel = new LeftPanel ();
  34. topPanel = new TopPanel (this);
  35. canvasPanel = new CanvasPanel ();
  36.  
  37. bottomPanel = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT, leftPanel, canvasPanel);
  38. bottomPanel.setDividerLocation (50);
  39. wholePanel = new JSplitPane (JSplitPane.VERTICAL_SPLIT, topPanel, bottomPanel);
  40. wholePanel.setDividerLocation (70);
  41.  
  42. // canvasPanel.addComponentListener(this);
  43.  
  44. this.getContentPane ().add (wholePanel);
  45. }
  46. /*
  47.   public void componentResized(ComponentEvent e)
  48.   {
  49.   System.out.println ("Hi there");
  50.   canvasPanel.repaint();
  51.   }
  52.  
  53.   public void componentMoved(ComponentEvent e)
  54.   {
  55.   }
  56.  
  57.   public void componentShown(ComponentEvent e)
  58.   {
  59.   }
  60.  
  61.   public void componentHidden(ComponentEvent e)
  62.   {
  63.   }*/
  64. }
  65.  
  66.  
  67. class LeftPanel extends JPanel
  68. {
  69. public LeftPanel ()
  70. {
  71. }
  72. }
  73.  
  74.  
  75. class TopPanel extends JPanel implements ActionListener, MouseListener
  76. {
  77. JButton repaintButton;
  78. ColorForms cf;
  79.  
  80. public TopPanel (ColorForms cForm)
  81. {
  82. cf = cForm;
  83. repaintButton = new JButton ("Repaint");
  84. repaintButton.addActionListener(this);
  85. add (repaintButton);
  86. this.addMouseListener(this);
  87. }
  88.  
  89. public void actionPerformed(ActionEvent e)
  90. {
  91. cf.canvasPanel.repaint ();
  92. }
  93.  
  94. public void mouseClicked(MouseEvent e)
  95. {
  96. cf.canvasPanel.repaint();
  97. }
  98.  
  99. public void mousePressed(MouseEvent e) {
  100. }
  101.  
  102. public void mouseReleased(MouseEvent e) {
  103. }
  104.  
  105. public void mouseEntered(MouseEvent e) {
  106. }
  107.  
  108. public void mouseExited(MouseEvent e) {
  109. }
  110. }
  111.  
  112.  
  113. class CanvasPanel extends JPanel implements MouseListener
  114. {
  115. int timesPainted = 0;
  116.  
  117. public CanvasPanel ()
  118. {
  119. this.addMouseListener(this);
  120. }
  121.  
  122.  
  123. public void paintComponent (Graphics g)
  124. {
  125. timesPainted++;
  126. System.out.print ("I am in CanvasPanel repaint. # of times painted = ");
  127. System.out.println (timesPainted);
  128.  
  129. int ovalCenterX = 100;
  130. int ovalCenterY = 100;
  131. int ovalWidth = 200;
  132. int ovalHeight = 100;
  133. int ovalUpperLeftX = ovalCenterX - ovalWidth / 2;
  134. int ovalUpperLeftY = ovalCenterY - ovalHeight / 2;
  135. double angle = 0.5;
  136.  
  137. super.paintComponent (g);
  138. Graphics2D g2 = (Graphics2D) g;
  139. g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  140. setBackground(Color.GREEN);
  141.  
  142. AffineTransform orig = g2.getTransform();
  143. AffineTransform af = new AffineTransform ();
  144. af.rotate(angle, ovalCenterX, ovalCenterY);
  145. g2.setTransform(af);
  146.  
  147. g2.setColor (Color.BLACK);
  148. g2.fillOval (ovalUpperLeftX, ovalUpperLeftY, ovalWidth, ovalHeight);
  149. g2.setTransform(orig);
  150. g2.setColor (Color.MAGENTA);
  151. g2.fillOval (250, 100, 50, 50);
  152. }
  153.  
  154. public void mouseClicked(MouseEvent e)
  155. {
  156. repaint ();
  157. }
  158.  
  159. public void mousePressed(MouseEvent e)
  160. {
  161. }
  162.  
  163. public void mouseReleased(MouseEvent e)
  164. {
  165. }
  166.  
  167. public void mouseEntered(MouseEvent e)
  168. {
  169. }
  170.  
  171. public void mouseExited(MouseEvent e)
  172. {
  173. }
  174. }
Featured Poster
Reputation Points: 2614
Solved Threads: 687
Posting Expert
VernonDozier is offline Offline
5,372 posts
since Jan 2008
Sep 15th, 2008
1

Re: Having problems rotating Shapes in JPanel

The problem is originating with your creation of the affine transform that you are rotating:
Java Syntax (Toggle Plain Text)
  1. AffineTransform af = new AffineTransform ();
If you change that to pass the original transform to the constructor, it works just fine:
Java Syntax (Toggle Plain Text)
  1. AffineTransform af = new AffineTransform (orig);
Without backtracing the stack on every repaint() call, I can't tell you for certain, but I would guess the new transform is getting generated against the frame context when you resize and using the CanvasPanel on the other events. The fact that it's an inner class of another visual component further clouds the issue.

Honestly, you don't need to create a new transform from scratch anyway. Just call rotate directly on the graphics context
Java Syntax (Toggle Plain Text)
  1. g2.rotate(angle, ovalCenterX, ovalCenterY);
and it behaves just fine.

Also, if you move the setVisible() call to the end of the ColorForms constructor, it will paint the components you added properly on construction.
Moderator
Featured Poster
Reputation Points: 3239
Solved Threads: 838
Posting Genius
Ezzaral is offline Offline
6,756 posts
since May 2007
Sep 15th, 2008
0

Re: Having problems rotating Shapes in JPanel

Actually, disregard the comment on the inner class. I just noticed that it is not actually an inner class of ColorForms.

Since the "jumping" occurs on a top-level repaint of the containment heirarchy and CanvasPanel is a component of "bottomPanel", the new transform seems to be created relative to the bottomPanel graphics context when the paintComponent() call comes down from that container. Your other events are calling repaint directly on the CanvasPanel and the transform is fine on those.
Moderator
Featured Poster
Reputation Points: 3239
Solved Threads: 838
Posting Genius
Ezzaral is offline Offline
6,756 posts
since May 2007
Sep 15th, 2008
0

Re: Having problems rotating Shapes in JPanel

All right! Now we're getting somewhere! Moving the setVisible line solved that half of the problem and using the original transform in the constructor solved the other part, at least for the way I have it now. I'm still playing around with it trying to expand on it to make it fit into my larger program, but I think I'm going to flag this one as solved. Thank you very much Ezzaral!
Featured Poster
Reputation Points: 2614
Solved Threads: 687
Posting Expert
VernonDozier is offline Offline
5,372 posts
since Jan 2008

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in Java Forum Timeline: Write numbers to words
Next Thread in Java Forum Timeline: Variation of the Monte Carlo form of finding Pi... I'm having a bit of trouble





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC