-1

I programmed a code for a cube which can be turned on all pivots. Now I tried to put in a loop with Thread.sleep but each time it repaints it just gives me the half cube or nothing (it's kinda flickering and faltering).

Maybe it doesn't work because my laptop is too slow but I don't think that this is the case.

Here's the code:

import java.awt.*;
import javax.swing.*;

public class Würfel1 extends JApplet {

Container container;
Dimension Screen = new Dimension(400,400);
double c[] = new double[8];
double wx = 90; double wy = 90; double wz = 90;

public Würfel1() {
    init();
}

public void init() {
    this.setSize(Screen);
    container = this.getContentPane();
}

public void paint(Graphics g) {
    super.paint(g);
    drawcube(g);
    wx = wx - 2;
    wy = wy + 1;
    wz = wz + 3;

    try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}

    repaint();
}

private void drawcube(Graphics g) {
    /*
     * Punkt links oben vorne
     */
    int xStart = 100;
    int yStart = 100;

    /*
     * Breite, Höhe und Länge des Körpers
     */
    int b = 200;
    int h = 200;
    int l = 200;

    /*
     * Winkel der X-, Y- und Z-Achse des Körpers
     */
//      int wx = 90;
//      int wy = 90;
//      int wz = 90;

    /*
     * Mittelpunkt des Körpers
     */
    int x = xStart + b/2;
    int y = yStart + h/2;

    /*
     * erzeugt die Grundwerte für den Winkel 90,90,90
     */
    double xfield[] = {(-b/2),(b/2),(b/2),(-b/2),(-b/2),(b/2),(b/2),(-b/2)};
    double yfield[] = {(-h/2),(-h/2),(h/2),(h/2),(-h/2),(-h/2),(h/2),(h/2)};
    double zfield[] = {(l/2),(l/2),(l/2),(l/2),(-l/2),(-l/2),(-l/2),(-l/2)};

    /*
     *  verändert die Werte unter Berücksichtigung der Winkel
     */
    for (int i = 0; i < 8; i++)
    {
        double newx,newy,newz;

        newy = yfield[i] * Math.cos(Math.PI*(90-wx)/180) - zfield[i] * Math.sin(Math.PI*(90-wx)/180);
        newz = yfield[i] * Math.sin(Math.PI*(90-wx)/180) + zfield[i] * Math.cos(Math.PI*(90-wx)/180);
        yfield[i] = newy;
        zfield[i] = newz;

        newx = xfield[i] * Math.cos(Math.PI*(90-wy)/180) - zfield[i] * Math.sin(Math.PI*(90-wy)/180);
        newz = xfield[i] * Math.sin(Math.PI*(90-wy)/180) + zfield[i] * Math.cos(Math.PI*(90-wy)/180);
        xfield[i] = newx;
        zfield[i] = newz;

        newx = xfield[i] * Math.cos(Math.PI*(90-wz)/180) - yfield[i] * Math.sin(Math.PI*(90-wz)/180);
        newy = xfield[i] * Math.sin(Math.PI*(90-wz)/180) + yfield[i] * Math.cos(Math.PI*(90-wz)/180);
        xfield[i] = newx;
        yfield[i] = newy;
    }

    for (int i = 0; i < 8; i++) {
        c[i] = 1;
    }

    /*
     * Malt die Linien des Körpers
     */
    DrawPolygon(0,1,2,3,xfield,yfield,x,y,g,1);
    DrawPolygon(6,5,4,7,xfield,yfield,x,y,g,2);
    DrawPolygon(5,1,0,4,xfield,yfield,x,y,g,3);
    DrawPolygon(3,2,6,7,xfield,yfield,x,y,g,4);
    DrawPolygon(2,1,5,6,xfield,yfield,x,y,g,5);
    DrawPolygon(4,0,3,7,xfield,yfield,x,y,g,6);

}

public void DrawPolygon(int a, int s, int d, int f, double[] xfield, double yfield[],int b,int h,Graphics g,int c) {
    if((xfield[a] - xfield[s]) * (yfield[d] - yfield[s])
              - (yfield[a] - yfield[s]) * (xfield[d] - xfield[s]) > 0) {
                // |j->i x j->k| > 0

                int xCoords[] = {(int)(xfield[a])+b,(int)(xfield[s])+b,
                                 (int)(xfield[d])+b,(int)(xfield[f])+b};
                int yCoords[] = {(int)(yfield[a])+h,(int)(yfield[s])+h,
                                 (int)(yfield[d])+h,(int)(yfield[f])+h};
                Color color = new Color(0,0,0);
                if (c == 1) color = new Color(255,0,0);
                if (c == 2) color = new Color(255,255,0);
                if (c == 3) color = new Color(0,255,0);
                if (c == 4) color = new Color(0,255,255);
                if (c == 5) color = new Color(0,0,255);
                if (c == 6) color = new Color(255,0,255);

                g.setColor(color);
                g.fillPolygon(xCoords, yCoords, 4);
    }
}

public static void main(String[] args) {
    new Würfel1();
}
}

I used this Idea because I saw it in another code, but there the Polygon is drawed with an Image called buffer (i do not really know what this is) I also use JApplet because its easier to use then a JFrame where i add my JPanel.

My latest try was to replace the try [...] catch [...] code with

        ActionListener action = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            repaint();
        }
    };
    new Timer(100,action).start();

but for some reason it just speeded up my applet and still had the problem i had. I already read in other question that they got a similar problem but i didnt find a way to solve mine in using the answers to this problem.

I now changed the normal draw[...] and put my cube on an image: ... first is right on top in the drawcube method

    // Double-Buffering
    if (buffer==null) {
        buffer=createImage(this.getSize().width, this.getSize().height);
        gBuffer=(Graphics2D)buffer.getGraphics();
    }
    gBuffer.clearRect(0,0, this.getSize().width, this.getSize().height);

    // Antialiasing
    gBuffer.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);

... the next quote is set in the end of drawcube

    g.drawImage(buffer,0,0,this);

... i also had to change the fillPoly method (which is quite obvious)

                gBuffer.setColor(color);
                gBuffer.fillPolygon(xCoords, yCoords, 4);

... i put a timer in the init method - now its almost working fine

public void init() {
    this.setSize(Screen);
    ActionListener action = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            repaint();
        }
    };
    new Timer(100,action).start();
}
Arcadia
  • 3
  • 2
  • 4
    "Thread.sleep" does what it's supposed to do, trust me on this one. I recommend you look at the rest of the code. – peter.petrov Dec 21 '13 at 23:00
  • Also, you're supposed to override paintComponent(), not paint(). – JB Nizet Dec 21 '13 at 23:01
  • 2
    Remarkably, `Thread.sleep()` is not broken. – Brian Roach Dec 21 '13 at 23:08
  • So when its not Thread.sleep() .... what is it then which causes this problem? – Arcadia Dec 21 '13 at 23:13
  • You're sleeping within the paint method of all places -- the absolute worst place to do it (although no place on the Swing event thread is good). Remember that all paint and paintComponent methods need to be lean, mean, and fast as can be since their speed is a major determinant in how your responsive your program appears to be to the user. Anything that slows them down, makes your program appear sluggish. Anything that sleeps them will grind your program to a complete halt. Use a Swing Timer as all other similar questions suggest. – Hovercraft Full Of Eels Dec 21 '13 at 23:20
  • 2
    Also, you'll want to exercise and improve your Google skills just a little bit more. A simple search on `Swing Thread sleep` will give you all the information you need. The current first four hits are to stackoverflow sites, [1](http://stackoverflow.com/q/14106953/522444), [2](http://stackoverflow.com/q/4215968/522444), [3](http://stackoverflow.com/q/16292498/522444), [4](http://stackoverflow.com/q/13486803/522444), and each would give you the same answer that you've received below. – Hovercraft Full Of Eels Dec 21 '13 at 23:27

1 Answers1

7

Don't:

  1. Use Thread.sleep() in a painting method. This will block the Event Dispatch Thread and prevent Swing from responding to events

  2. Invoke repaint() from within a painting() method. This will cause an infinite loop

  3. Override paint() for custom painting. Custom Painting is done by overriding the paintComponent(...) method of a JPanel (or JComponent). Then you add the panel to the applet.

Do:

  1. Use a Swing Timer to schedule animation.
camickr
  • 321,443
  • 19
  • 166
  • 288
  • I want an infinite loop. and i just tried a swingtimer and it just started to draw itself faster and faster and faster can you give me an example of HOW and WHERE to use it right in my code? – Arcadia Dec 21 '13 at 23:25
  • 2
    @user3126212: if you're getting that behavior, then you're doing something wrong, likely stacking method calls within the timer or adding more than one timer. Please don't ask us to write code for you or change your code. Instead **show us** your latest code as an edit to the bottom of your original question and describe in fair detail your program's misbehavior. Let us help you with ***your*** code. – Hovercraft Full Of Eels Dec 21 '13 at 23:29
  • Maybe, this question and answers to it clarify things furthermore: http://stackoverflow.com/questions/15264373/applet-flickers-even-after-using-using-double-buffering – akhikhl Dec 22 '13 at 00:12
  • @SamTiba, reread the `don't` points. You don't seem to have changed anything. The Timer should be started from the init() method, not a painting method. – camickr Dec 22 '13 at 00:42
  • @camickr so thats it??? seriously? couldn't you just have written that and helped me out? its still flickering but less than before ... i mean ... i can read 'donts' as long as i can - if there is no answer in it then what should i do? it woudlve been enough to say 'put a timer in the init method' nevertheless thanks – Arcadia Dec 22 '13 at 00:47
  • @SamTiba, `so thats it???` - yes that's it. I didn't think it needed anymore explanation. The idea of a Timer is to start it once. I was assuming that once you read the tutorial you would also understand that as well. You then know your code better than me so you would know the best place to start the Timer. – camickr Dec 22 '13 at 01:26