问题
I am making a Java applet for school whose function is to randomly select six numbers for coordinates of three points and connect them to make a triangle. It is only supposed to draw one triangle and find the "length of the sides". However when I put it on my website it will redraw itself multiple times.

I made another applet, simpler, that only selects 4 random numbers for coordinates to draw a line. Same problem.
The redrawing problem seems to happen when the user moves the screen, e.g. when I scroll or when I resize the applet viewer in Eclipse. My source code is posted here.
I appreciate any help! Thanks!
import javax.swing.JApplet;
import java.awt.*;
@SuppressWarnings("serial")
public class LineApplet extends JApplet {
/**
* Create the applet.
*/
static int width;
int height;
public void init() {
width = getSize().width;
height = getSize().height;
}
public static int[] randomLine() {
int[] pointArray = new int[4];
int x;
for (int i = 0; i < 4; i++) {
x = ((int)(Math.random()*(width/10-2)))*20+10;
pointArray[i] = x;
}
return pointArray;
}
public void paint(Graphics g) {
g.setColor(Color.blue);
int[] coords = new int[4];
coords = randomLine();
g.drawLine(coords[0], coords[1], coords[2], coords[3]);
g.drawString(coords[0]/10 + ", " + coords[1]/10, coords[0], coords[1]);
g.drawString(coords[2]/10 + ", " + coords[3]/10, coords[2], coords[3]);
int midpointx = (coords[0] + coords[2])/2;
int midpointy = (coords[1] + coords[3])/2;
g.drawString(midpointx/10 + ", " + midpointy/10, midpointx, midpointy);
}
}
回答1:
As pointed out by Reimues, you are re-generating your coords each time the applet is repaint.
The other problem with your paint
method is actually you're not clear the previous state of the graphics context (this would have being done by paint
, but you failed to respect it's functionality when you overrode it).
You have two choices.
- call
super.paint(g)
- call
super.paint(g)
and call Graphics#clearRect(int, int, int, int) or Graphics#fillRect(int, int, int, int)
You should also, very rarely, need to override the paint
method of top level containers. One of the reasons is that they're not double buffered, the other is the paint chain is complex and easily broken...
You're better off using a JPanel
(or such) and overriding the paintComponent
method instead...
UPDATED
I updated your code to demonstrate the issues.
public class TestBadApplet extends JApplet {
public void init() {
}
@Override
public void start() {
final LinePane linePane = new LinePane();
setLayout(new BorderLayout());
JButton update = new JButton("Update");
add(linePane);
add(update, BorderLayout.SOUTH);
update.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
linePane.regenerate();
}
});
}
protected class LinePane extends JPanel {
private int[] coords = new int[4];
public void regenerate() {
coords = randomLine();
repaint();
}
public int[] randomLine() {
int[] pointArray = new int[4];
int x;
for (int i = 0; i < 4; i++) {
x = ((int) (Math.random() * (Math.min(getWidth(), getHeight()) / 10 - 2))) * 20 + 10;
pointArray[i] = x;
}
return pointArray;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.blue);
g.drawLine(coords[0], coords[1], coords[2], coords[3]);
g.drawString(coords[0] / 10 + ", " + coords[1] / 10, coords[0], coords[1]);
g.drawString(coords[2] / 10 + ", " + coords[3] / 10, coords[2], coords[3]);
int midpointx = (coords[0] + coords[2]) / 2;
int midpointy = (coords[1] + coords[3]) / 2;
g.drawString(midpointx / 10 + ", " + midpointy / 10, midpointx, midpointy);
}
}
}
With super.paintComponent

Without super.paintComponent

回答2:
You are calculating new co-ordinates every time paint()
is called.
paint()
is called every time the applet window is resized or regains focus.
To fix, you could make
int[] coords = new int[4];
a class member variable and move
coords = randomLine();
to your init()
method, which will only be called once upon initialization.
Addendum:
Always call
super.paint(g);
when overridingpaint()
.For custom painting using Swing, the preferred approach is to extends a
JComponent
component leveraging the enhanced paint functionality offered by usingpaintComponent
.
For more see: Performing Custom Painting.
回答3:
The trouble seems to be that paint() is called every time the component needs repainting.
paint()
methods should be written in a way that doesn't produce side effects and they shouldn't change the internal state of the applet. paint()
must be restricted to doing just that: painting.
来源:https://stackoverflow.com/questions/13168078/java-applet-displays-itself-multiple-times