Java tehtäviä syventävät vastaus1

Mureakuha

Loikkaa: valikkoon, hakuun

Tehtävä:

Kirjoita kello. Piirrä kellotaulu ja viisarit drawLine()-metodilla. Varaa kerran sekunnissa toimiva Timer-säie ja kutsu sieltä repaint()-metodia, jolloin Java itse pyyhkii vanhat viisarit pois. Ohjelman täytyy osata skaalata viisarit oikean kokoisiksi riippumatta ikkunan koosta. Kellotaulun ympyrämuodon kaava voidaan laskea sin()- ja cos()-funktioilla. Kun origo on vasemmassa yläkulmassa, kaavan koordinaatit ovat muotoa,

  • Keskipiste: ikkunan_leveys/2-ikkunan_korkeus/2
  • X-koordinaatti: ikkunan_leveys/2+sin(x)*haluttu_etäisyys_keskipisteestä
  • Y-koordinaatti: ikkunan_korkeus/2-cos(x)*haluttu_etäisyys_keskipisteestä

jossa x on haluttu kulma radiaaneissa (00:00 on nolla ja 12:00 on 2*PII radiaania).

ClockFrame.java

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
 
/**
 * Ikkunaluokka.
 */
public class ClockFrame extends JFrame
{
  /** Kellotaulu */
  private ClockPanel clockPanel = new ClockPanel();
 
  /**
   * Konstruktori.
   */
  public ClockFrame()
  {
    JPanel contentPane = ( JPanel ) getContentPane();
    contentPane.setLayout( new BorderLayout() );
    setSize( new Dimension( 300, 300 ) );
    setTitle( "Kello" );
    setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
    contentPane.add( clockPanel, BorderLayout.CENTER );
  }
 
}

ClockPanel.java

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.util.*;
 
/**
 * Kellotaulupaneeli.
 */
public class ClockPanel extends JComponent
{
  /** Viisareiden piirtokynä */
  private BasicStroke pointerStroke = new BasicStroke( 2.0F );
  /** Kellotaulun piirtokynä */
  private BasicStroke tickStroke = new BasicStroke( 1.0F );
 
  /**
   * Panelin piirtometodi.
   * @param grfx piirtokonteksti
   */
  public void paintComponent( Graphics grfx )
  {
    Graphics2D g = ( Graphics2D ) grfx;
    g.setStroke( tickStroke );
    g.setColor( Color.black );
    Dimension size = this.getSize();
 
    for ( double x = 0; x < 2 * Math.PI; x = x + 0.5236 ) // sin() ja cos() käyttävät radiaaneja, 6.2832 == 2*PI
    {
      g.drawLine( ( int ) ( size.width / 2 + Math.sin( x ) * size.width * 0.45 ),
                  ( int ) ( size.height / 2 - Math.cos( x ) * size.height * 0.45 ),
                  ( int ) ( size.width / 2 + Math.sin( x ) * size.width * 0.4 ),
                  ( int ) ( size.height / 2 - Math.cos( x ) * size.height * 0.4 ) ); // piirtää kellotaulun
    }
 
    Calendar cal = Calendar.getInstance();
    int second = cal.get( Calendar.SECOND );
    int minute = cal.get( Calendar.MINUTE );
    int hour = cal.get( Calendar.HOUR );
 
    g.setStroke( pointerStroke );
    g.setColor( Color.blue );
    g.drawLine( ( int ) size.width / 2,
                ( int ) size.height / 2,
                ( int ) size.width / 2 + ( int ) ( Math.sin( 2 * Math.PI * second / 60 ) * size.width * 0.34 ),
                ( int ) size.height / 2 - ( int ) ( Math.cos( 2 * Math.PI * second / 60 ) * size.height * 0.34 ) ); // sekunnit
 
    g.drawLine( ( int ) size.width / 2,
                ( int ) size.height / 2,
                ( int ) size.width / 2 + ( int ) ( Math.sin( 2 * Math.PI * minute / 60 ) * size.width * 0.3 ),
                ( int ) size.height / 2 - ( int ) ( Math.cos( 2 * Math.PI * minute / 60 ) * size.height * 0.3 ) ); // minuutit
 
    g.drawLine( ( int ) size.width / 2,
                ( int ) size.height / 2,
                ( int ) size.width / 2 + ( int ) ( Math.sin( 2 * Math.PI * hour / 12 ) * size.width * 0.25 ),
                ( int ) size.height / 2 - ( int ) ( Math.cos( 2 * Math.PI * hour / 12 ) * size.height * 0.25 ) ); // tunnit
  }
 
}

ClockApp.java

import javax.swing.UIManager;
import java.awt.*;
 
/**
 * Varsinainen ohjelma.
 */
public class ClockApp
{
  private ClockFrame frame;
 
  /**
   * Luo ja rakentaa ohjelman.
   */
  public ClockApp()
  {
    frame = new ClockFrame();
    frame.validate();
 
    // keskittää ohjelman ruudun keskelle
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    Dimension frameSize = frame.getSize();
    if ( frameSize.height > screenSize.height )
      frameSize.height = screenSize.height;
 
    if ( frameSize.width > screenSize.width )
      frameSize.width = screenSize.width;
 
    frame.setLocation( ( screenSize.width - frameSize.width ) / 2, ( screenSize.height - frameSize.height ) / 2 );
 
    // näyttää ohjelman
    frame.setVisible( true );
 
    // luo ajastinsäikeen ja käynnistää sen
    ClockTimerThread r = new ClockTimerThread();
    Thread t = new Thread( r );
    t.setDaemon( true );
    t.start();
  }
 
  /**
   * Main-metodi.
   * @param args käynnistysparametrit
   */
  public static void main( String[] args )
  {
    try
    {
      UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
    }
    catch ( Exception e )
    {
      e.printStackTrace();
    }
    new ClockApp();
  }
 
  /**
   * Ajastin säie.
   */
  private class ClockTimerThread implements Runnable
  {
    boolean running = true;
 
    /**
     * Säikeen ajo ja olemassaolo.
     */
    public void run()
    {
      while ( running )
      {
        frame.repaint();
        try
        {
          // nukuttaa säikeen noin sekunnin ajaksi
          Thread.sleep( 950 );
        }
        catch ( InterruptedException e )
        {}
      }
    }
 
    /**
     * Pysäyttää säikeen ja aiheuttaa sen kuoleman.
     */
    public void stopIt()
    {
      running = false;
    }
  }
 
}
Tämän dokumentin kopiointi, levittäminen sekä muokkaaminen on sallittua GNU Free Documentation Licensen version 1.2 tai uudemman Free Software Foundationin julkaiseman version mukaisesti, ilman muuttumattomuuslauseketta tai kansitekstejä. Tätä koskee vastuuvapaus.
Kopio lisenssistä (englanniksi) löytyy täältä.

Alkuperäinen (c) Petteri Hämäläinen

Henkilökohtaiset työkalut