Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Möchte in Java eine Analoguhr programmieren, jedoch weiß ich nicht so genau wie ich die Bewegungen der Zeiger realisieren soll. Nachdem ich das Ziffernblatt entworfen hatte (g.drawArc (0,0,400,400,360,0) und alle drei Zeiger eingezeichnet waren (die Markierungen für die Minutenschritte und Fünfminutenschritte sind auch schon implementiert worden) muss ich jetzt noch die Zeiger irgendwie in Bewegung bekommen. Also z.B. der Sekundenzeiger muss jede Sekunde vorwärts springen und nach sechzig Sekungen muss der Minutenzieger eine Minute weiter...
Was könnte ich zur Realisierung machen?
Wie kann ich bei Java eigendlich die aktuelle Uhrzeit in das Applet implementieren?
um den Uhrzeiger vorwärts zu bewegen kannst Du immer eine Linie vom Mittelpunkt des Uhrkreises zum Kreisbogen ziehen.
einzelne Punkte auf dem Uhrkreis kann man mit dem Satz von Pythagoras ausrechnen (sinus/cosinus Berechungen in Java solltest Du auch mal probiert haben)
Dann kann man den 360 grad Kreis einfach in 60 Teile einteilen 360/60=6, also hast Du dann für alle 6 Grad eine Linie zu zeichnen, die einfach wieder gelöscht werden muß, wenn der Zeiger weiterspringt.
Die Minutenstriche und die Fünfminutenstriche habe ich in das Ziffernbalatt schon implementiert. Die Ausrichtung der einzelnnen Zeiger auf eine bestimmte Stelle funktioniert ebenfalls.
Wie kann ich den die Position des Zeigers löschen? Muss ich da nicht festlegen, das der Zeiger jede Sekunde gelöscht werden soll und jede Sekunde wieder auf einer anderen Stelle dargestellt werden soll?
Habe auf der Javaseite mal geschaut und das hier gefunden:
Code:
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
new Timer(delay, taskPerformer).start();
Bei Preform a task habe ich mal
Code:
g..drawLine (200,200,400,50);
eingetragen, aber wenn ich das Applet starte wir der Strich nicht angezeigt.
Wie mach ich das jetzt nun genau, dass der Strich 1 Sekunde angezeigt wird und dann nicht?
versucht?
Damit wird die paint()-Methode aufgerufen und alle Änderungen werden neu gezeichnet. Bevor Du die Uhr neu zeichnest, zeichnest Du den Hintergrund neu. Entweder in dem Du mit
Code:
clearRect(int x, int y, int width, int height)
einen bestimmten Bereich des Applets löscht, oder in der paint()-Methode, in der Du den Hintergrund jedesmal zu aller erst zeichnest.
Wenn ich "repaint" benutze fängt meine Uhr stark an zu flackern. Kann ich da irgendwie noch einen Parameter angeben der Festlegt wie viel mal in der Sekunde die Uhr aktualisiert werden soll?
Ich weiß nicht genau wie das Applet abgearbeitet wird. Habe zuerst eine Methode paint erstellt, wenn ich gedoch jetzt eine andere Methode erstelle wird diese nicht beachtet. Es wird immer nur die erste Methode ausfegührt. Wenn ich ohne Applets programmiere kann ich ja in der main - Methode die anderen aufrufen. Wie funktioniert das bei Applets?
Hm ja, das Flackern kommt zustande, weil jedes Mal vor dem Zeichnen der Uhr der Hintergrund gezeichnet wird, und somit die Uhr komplett gelöscht wird. Man kann das etwas beeinflussen, in dem man die update()-Methode überschreibt und sich die paint()-Methode möglichst nur auf's Zeichnen konzentriert. Das heißt, keinerlei Berechnungen in der paint()-Methode, sie muss sehr schnell sein. Manchmal liegt es auch nur einfach an der Reihenfolge, des Zeichnens. Außerdem ist der Einsatz eines Puffers zu empfehlen.
Die update()-Methode ist die Reaktion auf repaint(). Also füge sie doch mal ins Applet ein und experimentiere etwas mit paint() und update().
Code:
private Graphics offscreen; // Speicher internes "Zeichenblatt"
private Image buffer; // Pufferbild
...
public void init() {
buffer = createImage(width, height); //
offscreen = buffer.getGraphics();
...
}
public void start() {
repaint() //kann u. U. nötig sein
}
public void update(Graphics g) {
offscreen.setColor(getBackground());
offscreen.fillRect(0, 0, width, height); //Hintergrund mit Hintergrundfarbe füllen
//an dieser Stelle alles auf das offscreen image zeichen und damit das
//Bild im Hintergrund zum Zeichnen vorbereiten.
...
offscreen.setColor(getForeground()); //Fordergrundfarbe einstellen
//Texte auf's offscreen image schreiben
offscreen.drawString("Text", 20, 50);
...
//zum Schluss fertiges Bild auf den Bildschirm kopieren
g.drawImage(buffer, 0, 0, this);
paint(g);
}
So etwas in der Art könnte helfen. Diese Methode nenn man Double Buffering, also das schreiben in ein Speicher internes Bild (Offscreen Image).
Bei Applets wird in der init()-Methode zunächst erst mal alles initialisiert. Sie kommt dann der main()-Methode von Applikationen in ihrer Funktion recht nahe. Die eigentliche Ausführung des Applets kann dann auch in der start()-Methode erfolgen, die ihrerseits wieder private Methoden oder Objekte aufrufen und benutzen kann. Möglich ist es auch mit Threads zu arbeiten.
Edit: Am 21.07.2004 modifiziert. Code vom Double Buffering verbessert.
Noch ein paar Suchbegriffe für die Forum-Suchfunktion: Applet flackern, Grafik, Image, Bilder, Buffer, bewegen, verschieben
Jetzt müsste ich nur noch wissen, wie ich einstellen kann das ein Appletupdate jede Sekunde oder jede zweite Sekunde erfolgt. Der Zeider muss ja eine Sekunde lang stehen bleiben und dann verschwinden. Dann sollte 6° später der nächste Zeiger eine Sekunde lang stehn bleiben und dann wieder verschwinden...
Um das für Deine Zeiger zu programmieren, brauchst Du auf jeden Fall einen Thread, der jede Sekunde die aktuelle Zeit besorgt und an eine Methode weiter reicht, die das Ergebnis für Deine Zeigerstellung berechnet. Danach zeichnest Du die aktuelle Zeigerstellung.
Mit Threads kanne ich mich nicht so gut aus. Es müsste aber auch ohne irgendwie funktionieren.
Auf der Javaseite gibt es diese Beispiel:
Code:
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...Perform a task...
}
};
new Timer(delay, taskPerformer).start();
Dort kann man doch die Sekunden einstellen. Wie könnte ich das jetzt lösen? Beim Beispiel bedarf es noch an Erklärungshilfe!
Hm, mag funktionieren, weiß ich nicht. Du kannst aber folgende Klasse rein theoretisch in Dein Applet als innere Klasse programmieren. Also einfach in den Klassenrumpf des Applet einfügen. Ob's funktioniert, weiß ich jetzt aber auch nicht, ist nur so 'ne Idee.
Code:
ZeitGeber zg;
...
class ZeitGeber extends Thread {
public void run() {
while(!isInterrupt()) {
...
repaint();
try {
Thread.sleep(1000);
}
catch(InterruptedException e) {
interrupt();
}
}
}
}
public void init() {
...
zg = new ZeitGeber();
}
public void start() {
...
if(zg == null) {
zg = new ZeitGeber();
}
zg.start();
}
public void stop() {
zg.interrupt();
zg = null;
}
Ich habe mich mal ein bisschen mit dem TimerTask auseinander gesetzt.
Code:
public class TimerTaskDemo extends Applet
{
public void init ()
{
Timer timer = new Timer();
// nach 2 Sek geht's los
timer.schedule( new Task(), 2000 );
// nach 1 Sek geht's los und dann alle 5 Sekunden
timer.schedule( new Task(), 1000, 5000 );
}
}
class Task extends TimerTask
{
public void run()
{
System.out.println( "Ausgabe" );
}
}
Ausgegeben wir immer "Ausgabe" jede 5 Sekunden...
Ich weiß jetzt jedoch nicht genau wie ich die Methode Paint implementieren muss.
Code:
public void paint (Graphics g)
{
g.drawLine (200,200,400,50)
}
Wie kann ich jetzt nun die Methode paint implementieren, anstelle von System.out.println ?
Die paint-Methode wird ständig vom Betriebssystem (oder so) aufgerufen, d.h. du musst in der run-Methode ein Objekt verändern, dass in der paint-Methode gezeichnet wird bzw. eine Variable hochzählen wo ein Strich gezeichnet wird.
paint() ist eine "automatische" Methode, die von der VM aufgerufen wird. Z.B. wenn man die Fenstergröße ändert, oder die Maus über das Applet bewegt.
Eigentlich sollte das Ganze funktionieren, wenn Du in der run()-Methode die repaint()-Methode aufrufst.
Die run()-Methode enthält den Code, den der Thread abzuarbeiten hat.
Hier noch mal die ganz einfache, komplette Applet-Klasse, die eine Digitaluhr simuliert. Vielleicht kannst Du ja auch was für Deine analoge Variante gebrauchen.
Code:
import java.awt.*;
import java.applet.*;
import java.util.*;
import java.text.*;
public class DigitalUhrApplet extends Applet {
ZeitGeber zg;
String zeit;
Font schriftart;
class ZeitGeber extends Thread {
public void run() {
while(!isInterrupt()) {
DateFormat df = DateFormat.getTimeInstance();
zeit = df.format(new Date());
repaint();
try {
Thread.sleep(1000);
}
catch(InterruptedException e) {
interrupt();
}
}
}
}
public void init() {
zg = new ZeitGeber();
schriftart = new Font("Arial", Font.BOLD, 20);
}
public void start() {
if(zg == null) {
zg = new ZeitGeber();
}
zg.start();
}
public void stop() {
zg.interrupt();
zg = null;
}
public void paint(Graphics g) {
g.setFont(schriftart);
g.drawString(zeit, 0, 20);
}
}