Swing FClock

Status
Nicht offen für weitere Antworten.

Developer_X

Top Contributor
heye, ich arbeite ja gerade an diesem projekt mit componenten, ich wollte da auch eine "FClock" schreiben, wie bei jedem anderen componenten überschreibe ich das gemalte, doch leider funktioniert das ganze nicht, warum?
Java:
package future;

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


/**
 * @author Kevin Riehl <br>
 * 
 * "So that the Future will come,
 * and the Programmers in future,
 * will remember us,
 * at the beginning of Computers,
 * and JavaProgramming."
 */

@SuppressWarnings("serial")
public class FClock extends JButton
{
	//Attribute
	//DateFormat
	DateFormat dateformat = DateFormat.getTimeInstance();
	String date = "";
	Date d = new Date();	
	int rot = 0;
	@SuppressWarnings("deprecation")
	@Override
	protected void paintComponent(final Graphics g) 
	{
	    super.paintComponent(g);
	    g.setColor(getBackground());
	    g.fillRect(0,0,getSize().width,getSize().height);
	    d = new Date();
	    date = "" + dateformat.format(d);
	    g.setColor(getForeground());
	    g.drawString(""+date,getSize().width- getSize().width/2,getSize().height-getSize().height/2);
	    g.setColor(Color.white);
	    g.drawOval(1,1,getSize().width-2,getSize().height-2);
	    
	    if(d.getSeconds()!=0)
	    rot = 60/d.getSeconds();
	    else
	    rot = 0;
	    	
	    g.translate(getSize().width/2, getSize().height/2);
	    ((Graphics2D) g).rotate(Math.toRadians((int)(-rot)));
	    g.setColor(Color.black);
	    g.drawRect(0,0,1,1);
	}

}

schaut euch mal zeile 48 an,
wenn ich da "rot" anstatt "-rot" angebe, dann funktioniert dass, aber auch nur, wenn man entweder den componenten resized oder mit der maus drüber fährt, außerdem ist anstatt eines dünnen Pfeils ein riesiges graues viereck, wie kann ich das wegbekommen?
 

Ebenius

Top Contributor
Deine Komponente muss ja regelmäßig neu gezeichnet werden. Swing zeichnet nur dann neu, wenn sich etwas ändert. Das macht man über einen [c]javax.swing.Timer[/c] einen [c]ActionListener[/c] und die [c]repaint()[/c]-Methode. Den Rest findest Du sicher raus.

Die Rotationsrichtung ist immer entgegen dem Uhrzeigersinn.

Außerdem: Definier Dir besser ein [c]Calendar[/c]-Objekt in der Klasse und initialisiere dessen Uhrzeit im [c]ActionListener[/c] (der vom [c]javax.swing.Timer[/c] aufgerufen wird, s.o.). Dazu brauchst Du: [c]System.currentTimeMillis()[/c] und [c]Calendar.setTimeInMillis(long)[/c]. In der [c]paintComponent(Graphics)[/c]-Methode brauchst Du dann nur noch den Kalendar nach den Zeitkomponenten fragen und keine (teuere) Stringkonvertierung auszuführen:
Java:
final int second = calendar.get(Calendar.SECOND);
final int minute = calendar.get(Calendar.MINUTE);
// usw.
Außerdem berechnest Du die Rotation falsch. Wenn Du die Gradzahlen berechnen willst, musst Du von einem Vollkreis von 360° ausgehen:
Java:
final int rotDegress = 60.0 / seconds * 360;
Ebenius
 
Zuletzt bearbeitet:

Landei

Top Contributor
60 Sekunden entsprechen 360°
1 Sekunde entspricht also 360°/60 = 6°
also ist dein rot = (6*Sekunden)°
Und dann willst du bestimmt nicht deine gesamte Grafik rotieren lassen, oder? Denn rotiert wird um 0,0, nämlich der linken oberen Ecke. Soll heißen, du müsstest die Grafik so verschieben, dass der Rotationsmittlepunkt auf 0,0 liegt, rotieren und dann zurückverschieben. Schlechte Idee.
Einen Punkt kannst du selbst rotieren lassen:
x = xm + r * cos(winkelInBogenmaß)
y = ym - r * sin(winkelInBogenmaß)
 

Developer_X

Top Contributor
60 Sekunden entsprechen 360°
1 Sekunde entspricht also 360°/60 = 6°
also ist dein rot = (6*Sekunden)°
Und dann willst du bestimmt nicht deine gesamte Grafik rotieren lassen, oder? Denn rotiert wird um 0,0, nämlich der linken oberen Ecke. Soll heißen, du müsstest die Grafik so verschieben, dass der Rotationsmittlepunkt auf 0,0 liegt, rotieren und dann zurückverschieben. Schlechte Idee.
Einen Punkt kannst du selbst rotieren lassen:
x = xm + r * cos(winkelInBogenmaß)
y = ym - r * sin(winkelInBogenmaß)

heye, ihr seht ja ich will was lernen, ich bin inder achten nach den sommerferien, und ich wollt euch fragen, könnt ihr mir das beibringen mit "sinus cosanus und tanus"
mein mathelehrer begegnete mir mit der antwort, als ich ihn nach dieser sache gefragt hatte mit: "X, ich werde euch alles beibringen, das im Lehrplan steht, nicht mehr"
X = mein Name

also kann mir einer von euch erklären was das ist?
<hr>
zu meinem Problem:
das hat jetzt eigentlich geklapt, mit der richtigen richtung des zeigers, aber ich habe immer noch folgende Probleme:
1. der Zeiger ist kein zeiger, sondern ein riesiges viereck, wie soll ich das ändern?
2. der Zeiger bewegt sich nicht von allein, sondern wird nur bewegt, wenn man mit der maus drüber fährt, usw..

ich lese mir eure post noch einige weitere male aufmerksam durch, und versuche die probleme allein zu lösen, wenn ich es trotzdem nicht hinbekomme, melde ich mich noch mal bei euch,
danke schon mal, Developer_X

Der bisherige Code ist hier:
Java:
package future;

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


/**
 * @author Kevin Riehl <br>
 * 
 * "So that the Future will come,
 * and the Programmers in future,
 * will remember us,
 * at the beginning of Computers,
 * and JavaProgramming."
 */

@SuppressWarnings("serial")
public class FClock extends JButton
{
	//Attribute
	//DateFormat
	DateFormat dateformat = DateFormat.getTimeInstance();
	String date = "";
	Date d = new Date();	
	int rot = 0;
	
	public FClock()
	{
		
	}
	
	@SuppressWarnings("deprecation")
	@Override
	protected void paintComponent(final Graphics g) 
	{
	    super.paintComponent(g);
	    g.setColor(getBackground());
	    g.fillRect(0,0,getSize().width,getSize().height);
	    d = new Date();
	    date = "" + dateformat.format(d);
	    g.setColor(getForeground());
	    g.drawString(""+date,getSize().width- getSize().width/2,getSize().height-getSize().height/2);
	    g.setColor(Color.white);
	    g.drawOval(1,1,getSize().width-2,getSize().height-2);
	   
	    rot = d.getSeconds()*6;
    
	    g.translate(getSize().width/2, getSize().height/2);
	    ((Graphics2D) g).rotate(Math.toRadians((int)(rot)));
	    g.setColor(Color.black);
	    g.drawRect(0,0,1,1);
	}
}
 

newcron

Aktives Mitglied
Ich finde das treffend: Du nennst dein Projekt "Future" und unterdrückst deprecated-warnungen... DAS hat keine Zukunft. Verwende den GregorianCalendar oder System.currentTimeInMillis() und berechne dir die Sekunde und Stunde daraus.
 

Developer_X

Top Contributor
Ich finde das treffend: Du nennst dein Projekt "Future" und unterdrückst deprecated-warnungen... DAS hat keine Zukunft. Verwende den GregorianCalendar oder System.currentTimeInMillis() und berechne dir die Sekunde und Stunde daraus.

okay, ich setzte mich jetzt ma dran, bis dann, Developer_X
PS: hey das reimt sich ja,
wie wunderbar, ^^
 

Developer_X

Top Contributor
okay, ich habe mir mal eure Threads durchgelesen, mit dem
Java:
javax.swing.Timer
habe ich sehr wenig erfahrung, könntet ihr mir vielleicht da ein bisschen auf die Sprünge helfen, der Code wie er oben da steht, so ist er bei mir immer noch.
Im Grunde genommen will ich nur 2 Sachen, auf die eine ist bisher noch immer keiner eingegangen.

1.Problem, immer muss man mit der Maus drüber fahren, usw... , wie genau mit
Java:
javax.swing.Timer
kann ich bitte das machen?

2.Problem, immer wenn das ganze bewegt wird, dreht sich leider nicht ein strich, sondern ein ganzes viereck, dessen rotationsachsenpunkt sich auf dem mitelgrund des kreises befindet, versteht ihr? wie kann ich das machen, dass sich nur die linie bewegt, meint ihr, dass das gar nicht anders geht, bei den Graphics und Graphics 2D?

Vielleicht sollte ich in der zu überschreibenden paint methode, vielleicht das Graphics in ein Graphics2D Objekt translantieren, bevor ich überhaupt damit anfange, damit zu arbeiten?
 

Ebenius

Top Contributor
Zu 1. Eigentlich hab ich ja schon genug Hilfestellung dazu gegeben... Ein Timer (ich schreibe immer javax.swing mit dazu, weil es zwei Timer-Klassen im JRE gibt und hierfür der javax.swing.Timer der geeignete ist) sendet regelmäßig (oder einmalig, je nach Einstellung des Timer-Objekts) einen Event. Damit er weiß wohin der Event gesendet werden soll, hängt man ihm also einen Zuhörer (Listener) an. Im einfachsten Fall sieht das dann so aus:
Java:
import javax.swing.Timer;
...

public class XYZ implements ActionListener {
  private final Timer timer;
  public XYZ() {
    timer = new Timer (1000, this);
    timer.setRepeats(true);
    timer.start();
  }

  public void actionPerformed(ActionEvent e) {
    // Diese Methode wird einmal pro Sekunde vom Timer aufgerufen...
  }
}
Zum Neuzeichnen hat jede Komponente die Methode [c]repaint()[/c] die man in der ActionPerformed-Methode aufruft. Dann funktioniert's schonmal. Etwas schöner ist, wenn man die Methode [c]addNotify()[/c] überschreibt und in dieser (und nicht im Konstruktor) [c]timer.start()[/c] ruft, damit der Timer nicht sinnlos läuft, während die Komponente gar nicht in Benutzung ist. Genauso muss man den Timer auch wieder anhalten...
Java:
@Override
public void addNotify() {
  super.addNotify();
  timer.start();
}

@Override
public void removeNotify() {
  super.removeNotify();
  timer.stop();
}

Zu zweitens: Wieso benutzt Du nicht die [c]drawLine(...)[/c]-Methode des [c]Graphics[/c]-Objekts?

Ebenius
 

Developer_X

Top Contributor
Zu Problem 1:
Java:
package future;

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


/**
 * @author Kevin Riehl <br>
 * 
 * "So that the Future will come,
 * and the Programmers in future,
 * will remember us,
 * at the beginning of Computers,
 * and JavaProgramming."
 */

@SuppressWarnings("serial")
public class FClock extends JButton
{
	//Attribute
	//DateFormat
	DateFormat dateformat = DateFormat.getTimeInstance();
	String date = "";
	Date d = new Date();	
	int rot = 0;
	
	public FClock()
	{
		
	}
	
	@SuppressWarnings("deprecation")
	@Override
	protected void paintComponent(final Graphics g) 
	{
	    super.paintComponent(g);
	    g.setColor(getBackground());
	    g.fillRect(0,0,getSize().width,getSize().height);
	    d = new Date();
	    date = "" + dateformat.format(d);
	    g.setColor(getForeground());
	    g.drawString(""+date,getSize().width- getSize().width/2,getSize().height-getSize().height/2);
	    g.setColor(Color.white);
	    g.drawOval(1,1,getSize().width-2,getSize().height-2);
	    
	    rot = d.getSeconds()*6;
    
	    g.translate(getSize().width/2, getSize().height/2);
	    ((Graphics2D) g).rotate(Math.toRadians((int)(rot)));
	    g.setColor(Color.black);
	    g.drawLine(0,0,getSize().width/2,getSize().height/20);
	}

}
Das angehängte bild zeigt das ergebnis

Problem:2
Da setzt ich mich grad ma dran, warte
 

Developer_X

Top Contributor
zu problem 2:
Java:
package future;

import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;


/**
 * @author Kevin Riehl <br>
 * 
 * "So that the Future will come,
 * and the Programmers in future,
 * will remember us,
 * at the beginning of Computers,
 * and JavaProgramming."
 */

@SuppressWarnings("serial")
public class FClock extends JButton
{
	//Attribute
	//DateFormat
	DateFormat dateformat = DateFormat.getTimeInstance();
	String date = "";
	Date d = new Date();	
	int rot = 0;
	
	public FClock()
	{
		addActionListener(new XYZ());
	}
	
	@SuppressWarnings("deprecation")
	@Override
	protected void paintComponent(final Graphics g) 
	{
	    super.paintComponent(g);
	    g.setColor(getBackground());
	    g.fillRect(0,0,getSize().width,getSize().height);
	    d = new Date();
	    date = "" + dateformat.format(d);
	    g.setColor(getForeground());
	    g.drawString(""+date,getSize().width- getSize().width/2,getSize().height-getSize().height/2);
	    g.setColor(Color.white);
	    g.drawOval(1,1,getSize().width-2,getSize().height-2);
	    
	    rot = d.getSeconds()*6;
    
	    g.translate(getSize().width/2, getSize().height/2);
	    ((Graphics2D) g).rotate(Math.toRadians((int)(rot)));
	    g.setColor(Color.black);
	    g.drawLine(0,0,getSize().width/2,getSize().height/20);
	}

	private class XYZ implements ActionListener 
	{
		  private final Timer timer;
		  
		  public XYZ()
		  {
		    timer = new Timer (1000, this);
		    timer.setRepeats(true);
		    timer.start();
		  }	 
		  public void actionPerformed(ActionEvent e)
		  {
			  repaint();
		  }
		}
}
Das klappt ja schon ganz gut, nur das Problem mit dem Zeiger ist nicht gelöst.
 

Ebenius

Top Contributor
Stell einfach die Frage nochmal so, dass ich sie greifen kann. Hab ein bisschen den Überblick verloren.

Die innere Klasse XYZ benennst Du natürlich noch sinnvoll um, oder? Den Tipp mit addNotify() und removeNotify() solltest Du ebenso befolgen, weil's besser ist. Immerhin willst Du eine Komponentenbibliothek schreiben; da ist der Anspruch wesentlich höher, als wenn man nur ein paar Komponenten für sich selbst frickeln möchte.

Ebenius
 

Developer_X

Top Contributor
Stell einfach die Frage nochmal so, dass ich sie greifen kann. Hab ein bisschen den Überblick verloren.

Die innere Klasse XYZ benennst Du natürlich noch sinnvoll um, oder? Den Tipp mit addNotify() und removeNotify() solltest Du ebenso befolgen, weil's besser ist. Immerhin willst Du eine Komponentenbibliothek schreiben; da ist der Anspruch wesentlich höher, als wenn man nur ein paar Komponenten für sich selbst frickeln möchte.

Ebenius

okay mach ich.

PS: hier noch mal das Problem für dich, in einer Formulierung:
Es geht hier eigentlich nur noch um das rein zeichneriche, das Problem:
es wird erst im hintergrund ein kreis mit den zeiten gezeichnet, wie das, bild das ich oben angehängt habe angezeigt habe,

bevor der zeiger gezeichnet wird, wird das graphics rotiert, und zwar im winkel X
danach wird der zeiger gezeichnet, mit der methode "drawLine(x,y,x,y)"
aber leider wird nicht nur der zeiger gedreht, sondern auch noch ein graues vier eck "drumherum" wie kann ich das eliminieren?

Schau dir das bild oben an, hier noch mal die Paint Methode:
Java:
	@Override
	protected void paintComponent(final Graphics g) 
	{
	    super.paintComponent(g);
	    g.setColor(getBackground());
	    g.fillRect(0,0,getSize().width,getSize().height);
	    d = new Date();
	    date = "" + dateformat.format(d);
	    g.setColor(getForeground());
	    g.drawString(""+date,getSize().width- getSize().width/2,getSize().height-getSize().height/2);
	    g.setColor(Color.white);
	    g.drawOval(1,1,getSize().width-2,getSize().height-2);
	    
	    rot = d.getSeconds()*6;
    
	    g.translate(getSize().width/2, getSize().height/2);
	    ((Graphics2D) g).rotate(Math.toRadians((int)(rot)));
	    g.setColor(Color.black);
	    g.drawLine(0,0,getSize().width/2,getSize().height/20);
	}
 

Landei

Top Contributor
Auch wenn ich mich wiederhole: Ich halte es für schlecht, das ganze Graphics-Objekt wüst zu transformieren, nur weil man den Endpunkt einer Linie nicht ausrechnen will (wofür nette Forumsteilnehmer bereits die Formel geliefert haben).

Übrigens: Stört es nicht, wenn sich die Uhr "deformiert", wenn der Nutzer die Komponente endlos in die Länge zieht? Wäre es nicht besser, einen Kreis mit dem Radius Math.min(getSize().width/2, getSize().height/2) zu zeichnen? Sonst stimmt auch die Bewegung der Zeiger nicht.
 

Ebenius

Top Contributor
Du darfst das Graphics-Objekt nicht verändern. Ansonsten veränderst Du es für alle nachfolgenden Operationen einfach mit. Nach [c]paintComponent()[/c] wird [c]paintBorder()[/c] mit dem selben Objekt gezeichnet. Mit dem Objekt das Du transformiert hast.

Aus diesem Grund: Immer eine Kopie zum Zeichnen anlegen, wenn man das Graphics-Objekt verändert. Immer ganz genau so:
Java:
@Override
public void paintComponent(Graphics g) {
  super.paintComponent(g);

  g = g.create(); // eine Kopie benutzen, wenn man Graphics verändert
  try {
    // hier die ganzen Veränderungen am Graphics und dann zeichnen
  } finally {
    g.dispose(); // zerstört die Kopie
  }
}
[c]addNotify()[/c] und [c]removeNotify()[/c] sind Methoden aus der [c]JComponent[/c]-Klasse. Also musst Du sie natürlich in der Komponente überschreiben.

Ich halte es für schlecht, das ganze Graphics-Objekt wüst zu transformieren
Ich hatte weiter oben auch schon überlegt, ob ich mich darüber beschwere. Allerdings gehe ich pauschal davon aus, dass an der Stelle später nicht Linien sondern irgendwelche Bilder als Zeiger gezeichnet werden sollen. In dem Fall kommt man um eine Transformation entweder des Bildes oder des Grafikkontexts kaum herum. Kann mich aber auch irren.

Ebenius
 

Developer_X

Top Contributor
und wieder einmal, kann ich schweren Herzens nur sagen danke, ohne irgendwelche Mittel meinen Danke aussprechen zu können,.
 

Ebenius

Top Contributor
und wieder einmal, kann ich schweren Herzens nur sagen danke, ohne irgendwelche Mittel meinen Danke aussprechen zu können,.
Mein Herr, sollte sich in Euch erneut der Wunsch regen, in schwelgerischer Ausdrucksweise Schriftwerk dem Geiste entfließen zu lassen, so bitte ich höflichst darum, den dem vermeintlichen Leser gebührenden Respekt nicht durch mangelnde Achtung der gebotenen grammatikalischen und orthographischen Sorgfaltspflicht zu mindern.

Herzlichst, Euer Ebenius ;-)
 

M4x0r

Aktives Mitglied
Mein Herr, sollte sich in Euch erneut der Wunsch regen, in schwelgerischer Ausdrucksweise Schriftwerk dem Geiste entfließen zu lassen, so bitte ich höflichst darum, den dem vermeintlichen Leser gebührenden Respekt nicht durch mangelnde Achtung der gebotenen grammatikalischen und orthographischen Sorgfaltspflicht zu mindern.

Herzlichst, Euer Ebenius ;-)
:lol:
 

Developer_X

Top Contributor
Mein Herr, sollte sich in Euch erneut der Wunsch regen, in schwelgerischer Ausdrucksweise Schriftwerk dem Geiste entfließen zu lassen, so bitte ich höflichst darum, den dem vermeintlichen Leser gebührenden Respekt nicht durch mangelnde Achtung der gebotenen grammatikalischen und orthographischen Sorgfaltspflicht zu mindern.

Herzlichst, Euer Ebenius ;-)

:lol::applaus::toll:
bei nebenwirkung fragen sie ihren artzt oder apotheker:
:autsch::smoke::wuerg:
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben