1 Attachment(s)
What am I doing wrong? Shrinking circle leaves a smear.
Code:
package ntsh;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyGUI {
private MyPanel myPanel;
private int height = 50;
private int width = 50;
private int x = 54;
private int y = 225;
private int panelWidth;
private int center;
public void go() {
JFrame newFrame = new JFrame("MyGui test");
newFrame.setLayout(new BorderLayout());
JButton eastButton = new JButton("Increase!");
newFrame.add(eastButton, BorderLayout.EAST);
myPanel = new MyPanel();
newFrame.add(myPanel, BorderLayout.CENTER);
JButton westButton = new JButton("Decrease!");
newFrame.add(westButton, BorderLayout.WEST);
ActionListener doInc = new Increaser();
eastButton.addActionListener(doInc);
ActionListener doDec = new Decreaser();
westButton.addActionListener(doDec);
newFrame.add(myPanel, BorderLayout.CENTER);
newFrame.getContentPane().setPreferredSize(new Dimension(500, 500));
newFrame.pack();
newFrame.setVisible(true);
newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
panelWidth = getWidth();
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.blue);
g.fillOval(x, y, width, height);
}
}
private class Increaser implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
if (width <= panelWidth + 1) {
height += 2;
width += 2;
x = panelWidth / 2 - findCenter(height);
y = 500 / 2 - findCenter(height);
myPanel.repaint(x, y, width, height);
} else {
}
}
}
private class Decreaser implements ActionListener {
@Override
public void actionPerformed(ActionEvent arg0) {
if (width <= panelWidth + 1) {
height -= 2;
width -= 2;
System.out.println("Shrinked: " + height);
System.out.println("Shrinked: " + width);
x = panelWidth / 2 - findCenter(height);
y = 500 / 2 - findCenter(height);
System.out.println("Shrinked Centre x: " + x);
System.out.println("Shrinked Centre y: " + y);
myPanel.repaint(x, y, width, height);
} else {
}
}
}
public int findCenter(int sizeOfCircle) {
center = sizeOfCircle / 2;
return center;
}
public static void main(String[] args) {
MyGUI gui = new MyGUI();
gui.go();
}
}
The above is my code for a grow and shrink circle. I am stuck. Everything seems fine but when I shrink my circle, it leaves a smear. Something like this.
Attachment 2136
I've read up and they asked me to do a g.setColor(Color.white) and fill the panel using g.fillRect(0,0,getWidth(),getHeight()), but it still doesn't work.
Anyone can enlighten me? I don't need the code, just somewhere else I can look to. Thank you very much!
Re: What am I doing wrong? Shrinking circle leaves a smear.
I think what you're seeing is a geometrical "rounding" problem with bits of the old circle remaining when you shrink it.
The suggestion of painting the background (does that do anything in this case?) won't help because the rounding occurs when you say:
Code:
myPanel.repaint(x, y, width, height);
x and y may be a *little* too large (say 1 pixel) and width and height a little too small (say 2 pixels). From the look of it, it is the latter pair that are mostly to blame, but the easiest thing would be to tweak all 4. (Or just paint everything with circleDrawPanel.repaint().)
[Edit] Of course I don't mean you should change the values of those variables: just the values that are passed to the repaint() method as that determines what area gets updated.
Re: What am I doing wrong? Shrinking circle leaves a smear.
Hi pbrockway2,
Thanks for the quick reply. My goodness. I just tried a myPanel.repaint() and it worked like a charm. Could you explain this to me as to why it worked while my previous code didn't? Thank you!
Oh and would it be possible to allow me to edit my post above? It's the same reason as my previous thread. One is able to find this post if they key in the class's name. I would like to edit the class name as well as some of my methods so if any of my classmates stumble onto this post, they would not be able to copy it. Thank you!
Re: What am I doing wrong? Shrinking circle leaves a smear.
The difference is in the behaviour of the two repaint() methods. As always the API docs are a good source of information:
repaint(): "Repaints this component. If this component is a lightweight component, this method causes a call to this component's paint method as soon as possible. Otherwise, this method causes a call to this component's update method as soon as possible."
whereas repaint(x,y,width,height): "Repaints the specified rectangle of this component. If this component is a lightweight component..."
By using the second version you are essentially "cropping" the repaint to a specific rectangle. That's often a good thing because it reduces the amount of work that has to be done, but it is important that the rectangle defined by x/y/width/height actually includes all of the area that has changed.
As you have found it is not enough to calculate this area mathematically: you also have to take into account that you are working with a whole number of pixels and that, at best, only approximates a real circle. The rules for what pixels actually get painted when you draw, eg, a circle are spelt out in great detail in the documentation, but in practice the easiest thing to do is make the rectangle a little larger than what mathematics would suggest to ensure that the whole changed region is covered. Or, as in this case, just redraw the whole thing.