Applet in Alternative umschreiben

Nun, Applets waren lange die einzige Möglichkeit, Programme ins Web zu bringen. Und Java ist ja eine „einfache“ Sprache. Und es gibt viele schlechte Applets, die von anderen kopiert und zu noch schlechteren Applets umgebaut wurden. Kurz: Es gibt viel Mist da draußen. Und dieses „Dodekaeder“-Applet enthält einige Sachen, die man so nicht machen sollte.

An sich kann die Portierung von einem Applet zu einer Swing-Anwendung recht mechanisch ablaufen. Das Applet selbst wird ein JPanel, die init-Methode wird im Konstruktor aufgerufen, statt paint überschreibt man paintComponent, das händische double-buffering fällt weg, und Animationen laufen in einem eigenen Thread (kein sleep während des Zeichnens :frowning: ).

Hab’ das hier mal am Beispiel durchexerziert, aber auch da gibt es einiges, was man, wenn man es neu schreiben würde, so nicht machen würde. Das ist quasi die Variante, bei der nur die notwendigsten (und einige der schmerzhaftesten) Dinge geändert sind:

package bytewelt;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

// From http://www.jjam.de/Java/Applets/3D_Effekte/Dodekaeder.html
// Ported to Swing for 
// https://forum.byte-welt.net/t/applet-in-alternative-umschreiben/20222

public class Dodekaeder {

    
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
    
    private static void createAndShowGui()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new DodekaederPanel());
        f.setSize(500,500);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}


class DodekaederPanel extends JPanel
{
    // 20 Eckpunkte 1-20
    // mit je 3 Koordinaten 1,2,3
    double p[][] = new double[21][4];

    int x=1, y=2, z=3;

    DodekaederPanel()
    {
        init();
        startAnimation();
    }
    
    private void init()
    {
        setBackground(new Color(255,255,255));

        // Halbe Seitenlänge des eingeschriebenen Würfels
        double s = 100;

        // Höhe einer Dodekaeder-Kante über dem Würfel
        double h = s*0.5*(Math.sqrt(5)-1);

        // 20 Eckpunkte im lokalen Dodekaeder-Koordinatensystem
        // Nullpunkt = Mittelpunkt
        p[1][x] =    0;        p[1][y] =   -h;        p[1][z] = -(s+h);
        p[2][x] =    0;        p[2][y] =    h;        p[2][z] = -(s+h);
        p[3][x] =    s;        p[3][y] =   -s;        p[3][z] =  -s;
        p[4][x] =    s;        p[4][y] =    s;        p[4][z] =  -s;
        p[5][x] =   -s;        p[5][y] =    s;        p[5][z] =  -s;
        p[6][x] =   -s;        p[6][y] =   -s;        p[6][z] =  -s;
        p[7][x] =    s+h;      p[7][y] =    0;        p[7][z] =  -h;
        p[8][x] =  -(s+h);     p[8][y] =    0;        p[8][z] =  -h;
        p[9][x] =    h;        p[9][y] =    h+s;      p[9][z] =   0;
        p[10][x] =  -h;        p[10][y] =   h+s;      p[10][z] =  0;
        p[11][x] =  -h;        p[11][y] = -(s+h);     p[11][z] =  0;
        p[12][x] =   h;        p[12][y] = -(s+h);     p[12][z] =  0;
        p[13][x] =   s+h;      p[13][y] =   0;        p[13][z] =  h;
        p[14][x] = -(s+h);     p[14][y] =   0;        p[14][z] =  h;
        p[15][x] =   s;        p[15][y] =  -s;        p[15][z] =  s;
        p[16][x] =   s;        p[16][y] =   s;        p[16][z] =  s;
        p[17][x] =  -s;        p[17][y] =   s;        p[17][z] =  s;
        p[18][x] =  -s;        p[18][y] =  -s;        p[18][z] =  s;
        p[19][x] =   0;        p[19][y] =  -h;        p[19][z] =  s+h;
        p[20][x] =   0;        p[20][y] =   h;        p[20][z] =  s+h;
        
    }

    // Rotationswinkel in rad
    double ax = 0.01;
    double ay = 0.0075;
    double az = 0.005;

    int w = 200; // -> Weltkoordinaten
    double px, py, pz;

    @Override
    protected void paintComponent(Graphics gr) {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.setColor(getBackground());
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.BLACK);

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

        // Dodekaeder-Eckpunkte verbinden
        drawLine(g, 1,2);       drawLine(g, 2,4);        drawLine(g, 4,7);
        drawLine(g, 7,3);       drawLine(g, 3,1);        drawLine(g, 2,5);
        drawLine(g, 5,8);       drawLine(g, 8,6);        drawLine(g, 6,1);
        drawLine(g, 4,9);       drawLine(g, 9,10);       drawLine(g, 10,5);
        drawLine(g, 6,11);      drawLine(g, 11,12);      drawLine(g, 12,3);
        drawLine(g, 7,13);      drawLine(g, 8,14);       drawLine(g, 9,16);
        drawLine(g, 10,17);     drawLine(g, 11,18);      drawLine(g, 12,15);
        drawLine(g, 13,16);     drawLine(g, 16,20);      drawLine(g, 20,19);
        drawLine(g, 19,15);     drawLine(g, 15,13);      drawLine(g, 20,17);
        drawLine(g, 17,14);     drawLine(g, 14,18);      drawLine(g, 18,19);
    }

    public void drawLine(Graphics2D g, int i, int j) {
        g.drawLine(
            (int)(p**[x])+w,(int)(p**[y])+w,
            (int)(p[j][x])+w,(int)(p[j][y])+w);
    }
    
    private void startAnimation()
    {
        Thread t = new Thread(() -> 
        {
            while (true)
            {
                animationStep();
            }
        });
        t.setDaemon(true);
        t.start();
    }
    
    private void animationStep()
    {
        // Verzögerung
        try {Thread.sleep(20);}
        catch (InterruptedException e) {}

        for (int i=1;i<21;i++) {

            px = p**[x];
            py = p**[y];
            pz = p**[z];

            // Rotation um x-Achse
            p**[y] = py*Math.cos(ax)-pz*Math.sin(ax);
            p**[z] = py*Math.sin(ax)+pz*Math.cos(ax);

            py = p**[y];
            pz = p**[z];

            // Rotation um y-Achse
            p**[x] = px*Math.cos(ay)+pz*Math.sin(ay);
            p**[z] =-px*Math.sin(ay)+pz*Math.cos(ay);

            px = p**[x];

            // Rotation um z-Achse
            p**[x] = px*Math.cos(az)-py*Math.sin(az);
            p**[y] = py*Math.cos(az)+px*Math.sin(az);
        }
        repaint();
    }
    
}
1 „Gefällt mir“