Wskazówki godzinne zegara "nie płyną" tylko przeskakują od razu o całą godzinę

0
package lab7;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;






import javax.swing.JPanel;
import javax.swing.Timer;


public class MyPanel extends JPanel {
	Timer t;
	public MyPanel()
	{
		t = new Timer(100, new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				MyPanel.this.repaint();
			}});
		t.start();
	}

	public void paint(Graphics g){
		super.paint(g);
		
		int mx = this.getWidth()/2;
		int my = this.getHeight()/2;
		
		int r;
		
		if (mx<my)
			r=mx;
		else
			r=my;
		int m =10;
		r=r-m;

		g.setColor(Color.LIGHT_GRAY);
		g.fillOval(mx-r, my-r, 2*r, 2*r);
		
		g.setColor(Color.BLACK);
		g.drawOval(mx-r,my-r,2*r,2*r);
		
		g.fillOval(mx-5, my-5, 10, 10);
		
		
		Calendar c= Calendar.getInstance();
		
		int sec = c.get(Calendar.SECOND);
		int min = c.get(Calendar.MINUTE);
		int ho = c.getMaximum(Calendar.HOUR);
		
	
		float alfa = sec*6-90;
		float ralfa = (float) (alfa*Math.PI/180.0);
		
		int xk = (int) (mx+r*Math.cos(ralfa));
		int yk = (int) (mx+r*Math.sin(ralfa));
		
		g.drawLine(mx, my, xk, yk);
		
		Graphics2D g2d  = (Graphics2D)g;
		g2d.setStroke(new BasicStroke(3));
		
		float alfa2 = min*6-90;
		float ralfa2 = (float) (alfa2*Math.PI/180.0);
		
		int xkk = (int) (mx+r*Math.cos(ralfa2));
		int ykk = (int) (mx+r*Math.sin(ralfa2));
		
		g2d.drawLine(xkk, ykk, mx, my);
		
		float alfa3 = ho*30-90;
		float ralfa3 = (float) (alfa3*Math.PI/180.0);
		
		int xkkk = (int) (mx+r*Math.cos(ralfa3));
		int ykkk = (int) (mx+r*Math.sin(ralfa3));
		
		Graphics2D g3d = (Graphics2D)g;
		g3d.setStroke(new BasicStroke(6));
		
		g3d.drawLine(xkkk, ykkk, mx, my);
	}


	}

Tak jak w temacie. Chciałbym żeby wskazówki zarówno minutowa jak i godzinowa przez cały czas "płynęły", a nie wykonywały jeden skok, minutowa odpowiednio kiedy minie 60 sekund, a godzinowa kiedy minie 60 minut. Dodatkowe pytanie, czemu wskazówka godzinowa nie działa tak jak powinna?

1

No to nie wykonuj obliczeń na godzinach - wykorzystaj milisekundy.

1

Zamień też

int ho = c.getMaximum(Calendar.HOUR);

na

int ho = c.get(Calendar.HOUR);
0

Nie wiem jak to zrobić..

3

Masz kod dla wskazówki sekundowej, jej położenie zmienia się co 1/10 sekundy.
Przy okazji, wystarczy jedna zmienna typu Graphics2D, warto korzystać z metody g2.setRenderingHints(...) - koło lepiej wygląda.

        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);

            Graphics2D g2 = (Graphics2D)g;
            RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHints(rh);
            
            int mx = this.getWidth()/2;
            int my = this.getHeight()/2;
 
            int r;
 
            if (mx<my)
                r=mx;
            else
                r=my;
            int m =10;
            r=r-m;
 
            g2.setColor(Color.LIGHT_GRAY);
            g2.fillOval(mx-r, my-r, 2*r, 2*r);
 
            g2.setColor(Color.BLACK);
            g2.drawOval(mx-r,my-r,2*r,2*r);
 
            g2.fillOval(mx-5, my-5, 10, 10);
 
 
            Calendar c = Calendar.getInstance();
 
            int sec = c.get(Calendar.SECOND);
            int min = c.get(Calendar.MINUTE);
            int ho = c.get(Calendar.HOUR);
            int ms = c.get(Calendar.MILLISECOND);
 
 
            float alfa = (float)(sec+ms/1000.0)*6-90;
            float ralfa = (float) (alfa*Math.PI/180.0);
0

Wielkie dzięki, wszystko pięknie działa, zrobiłem na Twoim przykładzie. Mogę prosić o trochę objaśnienia? Czemu muszę jeszcze dzielić przez 1000 w przypadku sekund i ms? Rozumiem, że to tysięczna część ale dlaczego trzeba to zrobić?

1

Chyba źle czytasz ten wzór, przez 1000 dzielone są tylko milisekundy.
Trzynaście sekund i 500 milisekund, to 13.5 sekundy. 13.5s = 13s + (500/1000)ms. W Javie dzielenie liczb całkowitych daje wynik całkowity (500/1000 = 0), dlatego jest ms/1000.0.

0

Ok, już rozumiem. http://imgur.com/ZtVLMLY,k0UuEnH chciałem to odpalić z ciekawości, ale nie kompiluje.

1

Dodaj instrukcje importu Source => Add import.

0

Chciałbym skrócić wskazówki. Myślałem, że wystarczy odjąć coś od współrzędnych drugiego punktu, jednak wskazówka skraca się od godziny 12 do 6, a od 6 do 12 wydłuża.

g2.drawLine(mx, my, xk-50, yk-50);
0

Planuję jeszcze zrobić jakiś cyferblat, ale utknąłem. Rysuje tylko godzinę 1.

int hou = 1;
		int di[] = {0,1,2,3,4,5,6,7,8,9,10,11,12};
		int i;
		
		
		
		
		
		for(hou=1; hou<=12; hou++){
			int alfa4 = hou*30-90;
			float ralfa4 = (float)(alfa4*Math.PI/180.0);
			
			int xkkkk = (int) (mx+r*Math.cos(ralfa4));
			int ykkkk = (int) (mx+r*Math.sin(ralfa4));
			for(i=1;i==hou;i++){
			g2.drawString(""+di[i], xkkkk, ykkkk);
3

Pierwsze pytanie (w szkole nie uczą teraz geometrii?):

int xk = (int) (mx+(r-50)*Math.cos(ralfa));
int yk = (int) (my+(r-50)*Math.sin(ralfa));
g2.drawLine(mx, my, xk, yk);

Drugie pytanie (mi się efekt nie podoba, estetyczne rozmieszczenie napisów nie jest proste):

int di[] = {1,2,3,4,5,6,7,8,9,10,11,12};
for(int hou=1; hou<=12; hou++){
    int alfa4 = hou*30-90;
    float ralfa4 = (float)(alfa4*Math.PI/180.0);
 
    int xkkkk = (int) (mx+r*Math.cos(ralfa4));
    int ykkkk = (int) (mx+r*Math.sin(ralfa4));
    g2.drawString(""+di[hou-1], xkkkk, ykkkk); 
}

Prościej narysować taki bezcyfrowy cyferblat
clock.png

0

Ładnie to wygląda. Robię na razie godzinowe, ale nawet kiedy je skrócę, to i tak mi się to rozjedzie tak samo jak cyfry (w zasadzie już się rozjeżdża, nie jest idealnie na obwodzie).

int alfa5 = hou*30-90;
			float ralfa5 = (float)(alfa5*Math.PI/180.0);
			
			g2.setStroke(new BasicStroke());
			int xkkkkk = (int) (mx+r*Math.cos(ralfa5));
			int ykkkkk = (int) (mx+r*Math.sin(ralfa5));
			g2.drawLine(mx-5, my-5, xkkkkk, ykkkkk);
1
int x1,y1,x2,y2;
double angle;
g2.setStroke(new BasicStroke());
for(int i=0; i<12; i++){
    angle = 2*Math.PI*(i/12.0);
    x1 = (int)(r*Math.cos(angle))+mx;
    y1 = (int)(r*Math.sin(angle))+my;
    x2 = (int)((r-20)*Math.cos(angle))+mx;
    y2 = (int)((r-20)*Math.sin(angle))+my;                
    g2.drawLine(x1,y1,x2,y2); 
}
for(int i=0; i<60; i++){
    angle = 2*Math.PI*(i/60.0);
    x1 = (int)(r*Math.cos(angle))+mx;
    y1 = (int)(r*Math.sin(angle))+my;
    x2 = (int)((r-10)*Math.cos(angle))+mx;
    y2 = (int)((r-10)*Math.sin(angle))+my;                
    g2.drawLine(x1,y1,x2,y2); 
}
0

Bardzo dziękuję za pomoc.

Jeszcze tak na koniec, dlaczego minuty i sekundy podstawiamy do x6-90 a godziny do x30-90?

0

Forma ostatniego pytania sugeruje, że bgd == jabluszko. Jeśli tak jest, to nie rozumiem pytania. Ty napisałeś ten kod.

0

Nie to akurat nie autor tematu;) Jak obliczamy kat dla minut i sekund to wykonujemy minuty6-90 a dla godzin godziny30-90. Skąd się biorą te wartości?

0

Nie zastanawiałem się wcześniej nad tymi wzorami, na pierwszy rzut oka są błędne. Ja bym napisał tak (odejmowanie kąta 90 stopni wynika stąd, że zwyczajowo mierzy się kąty od półprostej w prawo, a na zegarze trzeba mierzyć od półprostej w górę):

double angle;
int hours = date.get(Calendar.HOUR);
int minutes = date.get(Calendar.MINUTE);
double seconds = date.get(Calendar.SECOND) + date.get(Calendar.MILLISECOND)/1000.0;
angle = 2*Math.PI*(seconds/60.0)-(Math.PI/2);
//wyliczenie i narysowanie wskazówki sekundowej
angle = 2*Math.PI*((minutes*60+seconds)/3600.0)-(Math.PI/2);
//wyliczenie i narysowanie wskazówki minutowej
angle = 2*Math.PI*((hours*60*60+minutes*60+seconds)/43200.0)-(Math.PI/2);
//wyliczenie i narysowanie wskazówki godzinowej

Tajemnicze 43200 w ostatnim wzorze to ilość sekund w 12 godzinach.

0

Wszystko jasne, dzięki.

0

Jak zmienić czcionkę lokalnie? (Nie wiem czy dobrze to ująłem)

g2.setFont(g2.getFont().deriveFont(30.0f));

Gdy tego użyłem za pierwszym razem wszystko było dobrze, do czasu ponownej potrzeby zmiany wielkości czcionki. Kiedy używam tego ponownie z inną wielkością czcionki zmienia mi wszystkie Stringia na tą czcionke, jakby ignorując poprzednią wielkość czcionki.

0

Nie wiem co w Twoim poście oznaczają zwroty za pierwszym razem i ponownie. Ale taki kod

g2.setFont(g2.getFont().deriveFont(20.0f));
g2.drawString("Wielkość 20",30,30);
g2.setFont(g2.getFont().deriveFont(40.0f));
g2.drawString("Wielkość 40",30,60);

działa poprawnie. Napisy mają różną wielkość.

1 użytkowników online, w tym zalogowanych: 0, gości: 1