ist es irgendwie möglich einen Kreis “nach und nach” (also wie ein Stift auf Papier) zu zeichnen?
Das einzige was ich bisher vollbracht habe sind vollständige Kreise die nach und nach größer werden, aber das ist nicht das was ich beabsichtige.
Google hat mir bisher auch nicht gesagt wie ich da anfangen könnte.
Das würde ich lieber wieder rausnehmen.
Grundsätzliche Todsünde: innerhalb der paint Methode einer Komponenten sleep aufrufen.
Diese Methoden sollten, möglichst zügig abgearbeitet werden.
Ebenfalls nicht schön: die paint eines JFrames zu überschreiben…
Besser den Winkel in einem separaten Thread, Timer o.ä. Schritt für Schritt erhöhen und daraus einfach nur repaint() auf die Komponent aufrufen, dazu z.B. die paintComponent eines JPanels überschreiben.
######EDIT#######
sehe gerade Du verwendest AWT nicht Swing, warum auch immer??? Da gilt dann natürlich Panel mit überschriebener paint
Warum AWT und nicht SWING? Weil das 15 Jahre alte Dingsbums hier halt AWT macht.
Warum sleep() und kein Panel? Weil das schneller zu testen ging als n Timer und hier sowieso nur das drawArc eingebaut wird.
Und zum gucken wie der Kreis “gemalt” wird reicht das.
interessanterweise flimmert der Kreis ein wenig, je nach Winkel
da könnte es besser sein, immer den vollen Kreis zu malen und einen Teil weiß zu übermalen
allerdings bisschen dicker weiß, sonst wieder Flimmern,
mit Clippen usw. geht es sicher noch besser
Ich habe mir auch eine kleine Demo geschrieben. Ein Flimmern des Kreises konnte ich nicht wahrnehmen. Größere Winkel, die in jedem Schritt hinzugefügt werden, lassen die Animation etwas unflüssig wirken, weil der Kreisbogen plötzlich ein ganzes Stück wächst.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DrawArcAnimationDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Arc Animation Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Rectangle bounds = new Rectangle(50, 50, 150, 150);
ArcData arcData = new ArcData(bounds, 90, 0, 2);
ArcAnimationPanel panel = new ArcAnimationPanel(arcData, 50);
panel.setPreferredSize(new Dimension(250, 250));
panel.start();
frame.add(BorderLayout.CENTER, panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
class ArcAnimationPanel extends JPanel {
private final ActionListener animator = new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
if (currentAngle >= 360) {
currentAngle = 0;
animationTimer.restart();
} else {
currentAngle += data.getAngleIncrementValue();
}
repaint();
}
};
private final Timer animationTimer;
private final ArcData data;
private int currentAngle;
public ArcAnimationPanel(ArcData data, int delay) {
super();
this.animationTimer = new Timer(delay, animator);
this.data = data;
this.currentAngle = data.getArcAngle();
}
public void start() {
animationTimer.start();
}
public void stop() {
animationTimer.stop();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = data.getBounds().x;
int y = data.getBounds().y;
int w = data.getBounds().width;
int h = data.getBounds().height;
int startAngle = data.getStartAngle();
g.drawArc(x, y, w, h, startAngle, currentAngle);
}
}
final class ArcData {
private final Rectangle bounds;
private final int startAngle, arcAngle;
private final int angleIncrementValue;
public ArcData(
Rectangle bounds,
int startAngle, int arcAngle,
int angleIncrementValue) {
this.bounds = new Rectangle(bounds);
this.startAngle = startAngle;
this.arcAngle = arcAngle;
this.angleIncrementValue = angleIncrementValue;
}
public Rectangle getBounds() { return new Rectangle(bounds); }
public int getStartAngle() { return startAngle; }
public int getArcAngle() { return arcAngle; }
public int getAngleIncrementValue() { return angleIncrementValue; }
}
Liegt es vieleicht an AWT? Mit Swing würde ich keine Flimmern erwarten da double buffered. Soweit ich weiß muss man das mit AWT selbst implementieren… ?
Ja, das liegt am nicht vorhandenen DoubleBuffering in AWT. In Swing sind Komponenten bereits von Hause aus doppelt gepuffert, daher wird dort auch nichts flimmern oder flackern.
In AWT muss das, was als nächstes auf den Bildschirm gezeichnet werden soll, auf einem Offscreen-Image vorbereitet werden.
Im Wiki ist mindestens ein Beitrag darüber zu finden.
ich meinte die exakten Pixel die gemalt/ für alle Zeit (bis zum nächsten Malen) in Stein bzw. in den Bildschirm gemeißelt werden,
nix mit Double Buffering, sondern welche Zeichenpixel bestimmt werden,
minimale Abweichungen, je nach Größe des Winkels im letzten angefangenen Viertel
wenn man mein Programm nimmt und das Stroke wegnimmt, also mit Weiß exakt drüber malt, sieht man vielleicht die schwarzen Punkte,
oder bei anderen nicht so
double ym = 100;
double t = 0;
double r = 50;
double x = xm + r * Math.cos(t * Math.PI);
double y = ym + r * Math.sin(t * Math.PI);
g.drawLine((int)x, (int)y, (int)x, (int)y);```
was soll denn das `t` darstellen?
und wo kommt die Variable zum Zuge die enthält wie weit der Kreis schon gezeichnet ist?
bei der Umrechtung von t multiplizierst du mit PI, bei der Verwendung kommt nochmal Faktor PI dazu,
t wächst in der Verwendung schnell,
bald zweiter und dritter Kreis, da zum Glück Verschiebung, so dass fehlende Punkte ergänzt werden
mit double t = arcAngle / 180.0; sieht es besser aus
ob die Anzahl der Zwischenschritte reichen hängt aber auch von der Darstellung, vom verwendeten Radius ab, bei 250 wieder deutliche Lücken…,
dann lieber Winkel in 0.1 Grad-Schritten usw., evtl. auch direkt t um 0.001 erhöhen usw.,
allgemeines Konzept zu überlegen, aus dem Radius kann man sicher ne Formel für passendes Schrittmaß finden,
oder naheliegend tatsächlich Linien malen, zwischen je zwei berechneten Punkten