// Sekuntikelloapletti.java (c) Kari Laitinen // http://www.naturalprogramming.com/ // 2001-03-31 File created. // 2010-02-18 Ohjelman modernisointi aloitettu. // 2011-02-11 Viimeisin muutos. /* Tässä ohjelmassa on käytössä Aikanaytto-niminen luokka jota voidaan hyödyntää esim. pelisovelluksissa, joissa on säie joka jatkuvasti luo uuden kuvan pelinäkymästä. Tuosta säikeestä pitää kutsua Aikanaytto-oliolle kayta_kelloa()-metodia. Lisäksi pitää kutsua paintComponent()-metodista piirra()-metodia. Mietittävää: Olisiko hyvä voida konfiguroida Aikanaytto siten että -- se ei esim. näytä sadasosia -- se laskee aikaa alaspäin, siis vähentäen -- sen käyttämä fontti voidaan määrätä "ulkoapäin" */ import java.awt.* ; import javax.swing.* ; import java.awt.event.* ; class Aikanaytto { Font aikafontti = new Font("TimesRoman", Font.BOLD, 72 ) ; // Seuraavat vakiot ovat mahdollisia muuttujan // komentojen_tila arvoja. static final int KOMENTO_KASITELTY = 0 ; static final int START_KOMENTO_ANNETTU = 1 ; static final int STOP_KOMENTO_ANNETTU = 2 ; static final int RESET_KOMENTO_ANNETTU = 3 ; static final int VALIAIKA_KOMENTO_ANNETTU = 4 ; int komentojen_tila = KOMENTO_KASITELTY ; // Seuraavat vakiot ovat mahdollisia muuttujan // kellon_tila arvoja. static final int KELLO_ODOTTAA_KAYNNISTYSTA = 11 ; static final int KELLO_ON_PYSAYTETTYNA = 12 ; static final int KELLO_MITTAA_JA_NAYTTAA_AIKAA = 14 ; static final int KELLO_NAYTTAA_VALIAIKAA = 15 ; int kellon_tila = KELLO_ODOTTAA_KAYNNISTYSTA ; long kellon_nayttama_aika = 0 ; long kellon_pysaytyksen_kokonaiskesto = 0 ; long ajan_mittauksen_aloitushetki = 0 ; long ajan_mittauksen_pysaytyshetki = 0 ; int aikatekstin_paikka_y ; int minuuttien_paikka_x, sekuntien_paikka_x, sadasosien_paikka_x ; JPanel isantapaneeli ; public Aikanaytto( int annettu_paikka_x, int annettu_paikka_y, JPanel annettu_isantapaneeli ) { isantapaneeli = annettu_isantapaneeli ; FontMetrics aikafontin_mitat = isantapaneeli.getFontMetrics( aikafontti ) ; // Aika nakyy ruudulla muodossa 00:00:00 int aikatekstin_osan_leveys = 2 * aikafontin_mitat.charWidth( '0' ) + aikafontin_mitat.charWidth( ':' ) ; int koko_aikatekstin_leveys = 3 * aikatekstin_osan_leveys ; minuuttien_paikka_x = annettu_paikka_x ; sekuntien_paikka_x = minuuttien_paikka_x + aikatekstin_osan_leveys ; sadasosien_paikka_x = sekuntien_paikka_x + aikatekstin_osan_leveys ; aikatekstin_paikka_y = annettu_paikka_y ; } public void kayta_kelloa() { if ( komentojen_tila == KOMENTO_KASITELTY ) { // Tama kohta on tassa ensimmaisena kellon toiminnan // nopeuttamiseksi. } else if ( komentojen_tila == STOP_KOMENTO_ANNETTU ) { if ( kellon_tila == KELLO_MITTAA_JA_NAYTTAA_AIKAA ) { ajan_mittauksen_pysaytyshetki = System.currentTimeMillis() ; kellon_tila = KELLO_ON_PYSAYTETTYNA ; } komentojen_tila = KOMENTO_KASITELTY ; } else if ( komentojen_tila == START_KOMENTO_ANNETTU ) { if ( kellon_tila == KELLO_ODOTTAA_KAYNNISTYSTA ) { // aikaa aletaan mitata Reset-komennon jalkeen ajan_mittauksen_aloitushetki = System.currentTimeMillis() ; kellon_tila = KELLO_MITTAA_JA_NAYTTAA_AIKAA ; } else if ( kellon_tila == KELLO_ON_PYSAYTETTYNA ) { kellon_pysaytyksen_kokonaiskesto = kellon_pysaytyksen_kokonaiskesto + System.currentTimeMillis() - ajan_mittauksen_pysaytyshetki ; kellon_tila = KELLO_MITTAA_JA_NAYTTAA_AIKAA ; } komentojen_tila = KOMENTO_KASITELTY ; } else if ( komentojen_tila == RESET_KOMENTO_ANNETTU ) { kellon_tila = KELLO_ODOTTAA_KAYNNISTYSTA ; kellon_pysaytyksen_kokonaiskesto = 0 ; ajan_mittauksen_pysaytyshetki = 0 ; komentojen_tila = KOMENTO_KASITELTY ; } else if ( komentojen_tila == VALIAIKA_KOMENTO_ANNETTU ) { // Tata ei ole viela toteutettu, eikä ilmeisesti tarvi toteuttaakaan, // koska STOP-komennolla saadaan väliaika selville. kellon_tila = KELLO_NAYTTAA_VALIAIKAA ; komentojen_tila = KOMENTO_KASITELTY ; } if ( kellon_tila == KELLO_MITTAA_JA_NAYTTAA_AIKAA ) { kellon_nayttama_aika = System.currentTimeMillis() - ajan_mittauksen_aloitushetki - kellon_pysaytyksen_kokonaiskesto ; } else if ( kellon_tila == KELLO_ON_PYSAYTETTYNA ) { // Tassa ei tarvitse edes maalata ruutua koska // vanha aika on jaanyt ruudulle. } else if ( kellon_tila == KELLO_ODOTTAA_KAYNNISTYSTA ) { kellon_nayttama_aika = 0 ; } else if ( kellon_tila == KELLO_NAYTTAA_VALIAIKAA ) { // tata ei viela ole toteutettu } } public void aloita_ajan_mittaus() { komentojen_tila = START_KOMENTO_ANNETTU ; } public void pysayta_ajan_mittaus() { komentojen_tila = STOP_KOMENTO_ANNETTU ; } public void resetoi_kello() { komentojen_tila = RESET_KOMENTO_ANNETTU ; } public void piirra( Graphics graphics ) { Font alkuperainen_fontti = graphics.getFont() ; graphics.setFont( aikafontti ) ; int uudet_minuutit = (int) kellon_nayttama_aika / 60000 ; int uudet_sekunnit = (int) ( kellon_nayttama_aika % 60000 ) / 1000 ; int uudet_sadasosat = (int) ( kellon_nayttama_aika % 1000 ) / 10 ; graphics.drawString( String.format( "%02d:", uudet_minuutit ), minuuttien_paikka_x, aikatekstin_paikka_y ) ; graphics.drawString( String.format( "%02d:", uudet_sekunnit ), sekuntien_paikka_x, aikatekstin_paikka_y ) ; graphics.drawString( String.format( "%02d", uudet_sadasosat ), sadasosien_paikka_x, aikatekstin_paikka_y ) ; graphics.setFont( alkuperainen_fontti ) ; } } class SekuntikelloPanel extends JPanel implements Runnable, ActionListener { Thread kellonkayttosaie ; boolean saietta_on_suoritettava = false ; // Luodaan Aikanaytto-olio paikkaan ( 120, 150 ) mikä viitaa // aikatekstin vasempaan alakulmaan. Aikanaytto aikanaytto = new Aikanaytto( 120, 150, this ) ; JButton start_nappula, stop_nappula, reset_nappula ; public SekuntikelloPanel( int annettu_leveys, int annettu_korkeus ) { setLayout( new BorderLayout() ) ; JPanel nappulapaneeli = new JPanel() ; start_nappula = new JButton( "Start" ) ; stop_nappula = new JButton( "Stop" ) ; reset_nappula = new JButton( "Reset" ) ; start_nappula.addActionListener( this ) ; stop_nappula.addActionListener( this ) ; reset_nappula.addActionListener( this ) ; nappulapaneeli.add( start_nappula ) ; nappulapaneeli.add( stop_nappula ) ; nappulapaneeli.add( reset_nappula ) ; add( "South", nappulapaneeli ) ; } public void start_animation_thread() { if ( kellonkayttosaie == null ) { kellonkayttosaie = new Thread( this ) ; saietta_on_suoritettava = true ; kellonkayttosaie.start() ; } } public void stop_animation_thread() { if ( kellonkayttosaie != null ) { kellonkayttosaie.interrupt() ; // keskeytä mahdollisesti nukkuva säie saietta_on_suoritettava = false ; kellonkayttosaie = null ; } } public void run() { while ( saietta_on_suoritettava == true ) { aikanaytto.kayta_kelloa() ; repaint() ; try { Thread.sleep( 20 ) ; } catch ( InterruptedException vangittu_poikkeus ) { saietta_on_suoritettava = false ; } } } public void actionPerformed( ActionEvent tapahtuma ) { if ( tapahtuma.getSource() instanceof JButton ) { if ( tapahtuma.getSource() == start_nappula ) { aikanaytto.aloita_ajan_mittaus() ; } else if ( tapahtuma.getSource() == stop_nappula ) { aikanaytto.pysayta_ajan_mittaus() ; } else if ( tapahtuma.getSource() == reset_nappula ) { aikanaytto.resetoi_kello() ; } } } public void paintComponent( Graphics graphics ) { super.paintComponent( graphics ) ; aikanaytto.piirra( graphics ) ; } } public class Sekuntikelloapletti extends JApplet { SekuntikelloPanel ajanlaskentapaneeli ; public void init() { ajanlaskentapaneeli = new SekuntikelloPanel( getSize().width, getSize().height ) ; getContentPane().add( ajanlaskentapaneeli ) ; } public void start() { ajanlaskentapaneeli.start_animation_thread() ; } public void stop() { ajanlaskentapaneeli.stop_animation_thread() ; } }