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 ).
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();
}
}