TTimer ja GUI

javaopiskelija

TTimer ja GUI

Jos haluaisin luoda oman javaluokan joka toimii mahdollisimman samalla tavalla kuin Delphin TTimer -luokka (jossa OnTimer -property/tapahtumakäsittelijakoukku), niin..

mikä olisi paras tapa tuon tekemiseen?

Javassa on ilmeisesti useitakin tapoja ajastimen luomiseen, mutta nyt on tärkeää se, että omassa ohjelmassa olevaa metodia kutsutaan

samassa säikeessä kuin esim. graafisella lomakkeella olevaa BUTTONia painettaessa.

Monissa GUI -systeemeissähän graafisen käyttöliittymän käsittely on sallittua vain yhdestä säikeestä.

Noita GUI:tahan javalle on ainakin:

Swing
AWT

ja sitten vielä J2ME:n käyttämä systeemi.

Tarkoitus olisi siis kehittää sellainen TTimer -luokka, joka:

* olisi säieturvallinen siinä mielessä, että ajastimen lauetessa ajastinkäsittelijästä (käyttäjän omassa koodissa, eli TTimer -luokka ei sisällä ajastinkäsittelijää, vaan "koukun" joka mahdollistaa käyttäjän oman ajastinkäsittelijän kutsumisen ajastimen lauetessa) käsin voi turvallisesti päivittää GUI -käyttöliittymää, olkoonpa se sitten Swing, AWT tai mobiililaitteessa J2ME:n yhteydessä käytettävä systeemi

Minkä tahansa säikeen luominen (ja mahd. TRunnable -liittymän käyttö) ei siis välttämättä ole hyvä idea, koska tällöin ajastinkäsittelijää kutsutaan eri säikeestä kuin mistä käsin GUI -liittymää on turvallista päivittää.

Mikä siis vaihtoedhoksi ?


Tuohan on usein tarpeen jos vaikka halutaan noutaa http -protokollalla netistä jotakin, eikä haluta ohjelman käyttöliittymän "jäätyvän" odotettaessa mahdollisesti ruuhkautunutta tai epäkunnossa olevaa nettipalvelinta tai jos nettiyhteydessä on häiriöitä.

10

699

    Vastaukset

    Anonyymi (Kirjaudu / Rekisteröidy)
    5000
    • fidel1

      Javasta löytyy java.util.Timer-luokka (http://java.sun.com/javase/6/docs/api/java/util/Timer.html ), jolla ajastetaan java.util.TimerTask-instansseja (http://java.sun.com/javase/6/docs/api/java/util/TimerTask.html ). TimerTask:in perivän luokan pitää toteuttaa run-metodi, joka siis suoritetaan Timer-luokassa määritellyin intervallein. Eli ajastus hoitunee noiden avulla helposti.

      Itse käyttöliittymän päivitys voidaan sitten hoitaa siihen tarkoitetussa säikeessä. Yleensä käyttöliittymäkirjasto tarjoaa jonkin tavan päästä kyseiseen säikeeseen kiinni. Esim. swingiä käytettäessä kannattaa tutustua javax.swing.SwingWorker-luokkaan (http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html ) ja swing-tutoriaalin rinnakkaisajo-osuuteen (http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html ).

      • javaopiskelija

        Siis tarkoitus olisi tehdä Javalla jotain mahdollisimman samantapaista kuin TTimer -luokka on Delphissä.

        Delphissähän TTimer -luokka tarjoaa OnTimer -ominaisuuden, jolle voidaan:

        var
        T1 : TTimer;

        procedure TForm1.OnCreate(Sender:TObject);
        begin

        //
        T1.OnTimer := Timer1Timer;

        end;

        procedure TForm1.Timer1Timer(Sender:TObject);
        begin

        // Tätä rutiinia kutsutaan automaattisesti aina, kun ajastin Timer1 laukeaa.
        // Delphin TTimer -komponentti takaa, että sitä kutsutaan ohjelman pääsäikeestä; Delphissä tämä on AINA sama säie kuin se, josta graafisen käyttöliittymän päivitys on sallittua ja turvallista.

        //
        T1.Enabled := False; // estää ajastimen toistuvan laukeamisen kytkemällä ajastimen pois päältä kun se laukeaa 1. kerran

        end;

        En siis tee mitään sellaisella ajastimella, jonka tapahtumakäsittelijälle ei voida taata, että ajastin kutsuu sitä vain siitä säikeestä, josta GUI -päivitys on ok.

        Ainoa poikkeus: Jos Javassa voi tehdä (käyttöjärjestelmäriippumattomalla tavalla) jotain vastaavaa kuin MS-windowsissa PostMessage -funktiolla, jolloin "vääränlaisen" ajastimen tapahtumakäsittelijässä voisi:

        PostMessage(Form1.Handle, WM_Safetimer, 0, 0);

        ja sitten TForm1 -luokassa pitäisi:

        procedure WMSafetimer(var Msg:TWmTimer); message WM_Safetimer;

        Windowsissahan PostMessage:lla voi lähettää windows -sanoman määrätylle ikkunalle (Delphissä TForm -luokan Handle -ominaisuus palauttaa ikkunakahvan), ja käyttöjärjestelmä takaa, että tuo sanoma käsitellään siinä säikeessä, joka sanoman vastaanottavan ikkunan on luonut.

        Eli sellaisesta ajastimesta joka ei takaa ajastinkäsittelyä oikeassa säikeessä, olisi hyötyä vain, jos javasta löytyy käyttöjärjestelmäriippumaton tapa tehdä vastaavaa kuin em. windows/Delphi -esimerkissä PostMessage():n avulla on tehty.

        Löytyykö?

        Ja jos löytyy, voi toki ihmetellä, miksei javassa ole jotain TGuiTimer -tyyppistä luokkaa, joka hoitaa tuon oikeassa säikeessä kutsumisen automaattisesti.

        Toki mielellään niin, että sama luokka joko sellaisenaan, tai sitten siitä on 2 eri versiota, toimii sekä J2ME että J2SE -ympäristöissä.


      • fidel1
        javaopiskelija kirjoitti:

        Siis tarkoitus olisi tehdä Javalla jotain mahdollisimman samantapaista kuin TTimer -luokka on Delphissä.

        Delphissähän TTimer -luokka tarjoaa OnTimer -ominaisuuden, jolle voidaan:

        var
        T1 : TTimer;

        procedure TForm1.OnCreate(Sender:TObject);
        begin

        //
        T1.OnTimer := Timer1Timer;

        end;

        procedure TForm1.Timer1Timer(Sender:TObject);
        begin

        // Tätä rutiinia kutsutaan automaattisesti aina, kun ajastin Timer1 laukeaa.
        // Delphin TTimer -komponentti takaa, että sitä kutsutaan ohjelman pääsäikeestä; Delphissä tämä on AINA sama säie kuin se, josta graafisen käyttöliittymän päivitys on sallittua ja turvallista.

        //
        T1.Enabled := False; // estää ajastimen toistuvan laukeamisen kytkemällä ajastimen pois päältä kun se laukeaa 1. kerran

        end;

        En siis tee mitään sellaisella ajastimella, jonka tapahtumakäsittelijälle ei voida taata, että ajastin kutsuu sitä vain siitä säikeestä, josta GUI -päivitys on ok.

        Ainoa poikkeus: Jos Javassa voi tehdä (käyttöjärjestelmäriippumattomalla tavalla) jotain vastaavaa kuin MS-windowsissa PostMessage -funktiolla, jolloin "vääränlaisen" ajastimen tapahtumakäsittelijässä voisi:

        PostMessage(Form1.Handle, WM_Safetimer, 0, 0);

        ja sitten TForm1 -luokassa pitäisi:

        procedure WMSafetimer(var Msg:TWmTimer); message WM_Safetimer;

        Windowsissahan PostMessage:lla voi lähettää windows -sanoman määrätylle ikkunalle (Delphissä TForm -luokan Handle -ominaisuus palauttaa ikkunakahvan), ja käyttöjärjestelmä takaa, että tuo sanoma käsitellään siinä säikeessä, joka sanoman vastaanottavan ikkunan on luonut.

        Eli sellaisesta ajastimesta joka ei takaa ajastinkäsittelyä oikeassa säikeessä, olisi hyötyä vain, jos javasta löytyy käyttöjärjestelmäriippumaton tapa tehdä vastaavaa kuin em. windows/Delphi -esimerkissä PostMessage():n avulla on tehty.

        Löytyykö?

        Ja jos löytyy, voi toki ihmetellä, miksei javassa ole jotain TGuiTimer -tyyppistä luokkaa, joka hoitaa tuon oikeassa säikeessä kutsumisen automaattisesti.

        Toki mielellään niin, että sama luokka joko sellaisenaan, tai sitten siitä on 2 eri versiota, toimii sekä J2ME että J2SE -ympäristöissä.

        Satuitko edes vilkaisemaan noita linkkejä? Sen SwingWorker-luokan avulla nimenomaan varmistetaan, että halutut rutiinit suoritetaan Swingin GUI-säikeessä. Sillä ei ole mitään merkitystä, mistä säikeessa SwingWorkerin metodeja kutsutaan.

        Mutta jos java.util.Timer tuntui liian monimutkaiselta homman suorittamiseen, on tarjolla myös javax.swing.Timer-luokka, joka on ehkä lähempänä tuota Delphin viritystä..

        Kuitenkin, jos haluaa oikeasti oppia koodaamaan uudella kielellä, kannattaa ehkä olla yrittämättä tehdä kaikkea samalla tavalla kuin jossain toisessa kielessä. Kielten rakenteet ja paradigmat ym. ovat kuitenkin yleensä sen verran erilaisia, että se ratkaisu mikä tuntuu parhaalta yhdessä ympäristössä ei välttämättä sovi ollenkaan toiseen. Javaa opetellessa kannattaa lukea tiiviisti API-dokumentaatiota ja Sunin tutoriaaleja, kyllä siellä on yleensä otettu kaikki normaalisti vastaantulevat tilanteet huomioon.


      • javaopiskelija
        fidel1 kirjoitti:

        Satuitko edes vilkaisemaan noita linkkejä? Sen SwingWorker-luokan avulla nimenomaan varmistetaan, että halutut rutiinit suoritetaan Swingin GUI-säikeessä. Sillä ei ole mitään merkitystä, mistä säikeessa SwingWorkerin metodeja kutsutaan.

        Mutta jos java.util.Timer tuntui liian monimutkaiselta homman suorittamiseen, on tarjolla myös javax.swing.Timer-luokka, joka on ehkä lähempänä tuota Delphin viritystä..

        Kuitenkin, jos haluaa oikeasti oppia koodaamaan uudella kielellä, kannattaa ehkä olla yrittämättä tehdä kaikkea samalla tavalla kuin jossain toisessa kielessä. Kielten rakenteet ja paradigmat ym. ovat kuitenkin yleensä sen verran erilaisia, että se ratkaisu mikä tuntuu parhaalta yhdessä ympäristössä ei välttämättä sovi ollenkaan toiseen. Javaa opetellessa kannattaa lukea tiiviisti API-dokumentaatiota ja Sunin tutoriaaleja, kyllä siellä on yleensä otettu kaikki normaalisti vastaantulevat tilanteet huomioon.

        Tuo swing- luokka on yhdessä mielessä todella ikävä:

        Jos ratkaisu tehdään sillä, niin sama työ joudutaan tekemään 3 kertaan:

        1. kerran swing.Timer -luokalla

        2. kerran AWT:n vastaavalla

        ja vielä 3. kerran jollain, mikä toimii J2ME ympäristössä.

        Tämän takia mielellään tekisin homman jollain sellaisella keinolla, joka on kelvollinen sekä swingissä, AWT:ssä että myös J2ME:ssä.

        Olen joskus itse rakentanut javaluokan, joka periaatteessa toimii mahdollisimman samoin kuin Delphin TTimer -luokka (pieniä eroja toki on, johtuen Delphin ja Javan erilaisesta tavasta käsitellä tapahtumakäsittelijöiden hallintaa).

        Mutta tuo oma TTimer -luokka muistaakseni on puutteellinen juuri siksi, että se ratkaisee vain osan ongelmaa:

        Se kyllä kutsuu jotain rutiinia määrävälein, mutta ei mitenkään takaa, mistä säikeestä kutsutaan. Tästä syystä tuo vaatisi muokkausta siten, että joko koko käytetty ajatintyyppi on vaihdettava toiseksi, sellaiseksi joka laukeaa siinä säikeessä, jossa GUI -käsittely on OK, tai sitten se vaatisi tuekseen jotain samantapaista kuin windowsissa on PostMessage.

        Eikö javan pitänyt olla laite- ja käyttöjärjestelmäriippumaton ohjelmointikieli / - väline / -ympäristö ?

        Tämä ei käytännössä toteudu kovinkaan hyvin, jos jokaisen hyödyllisen javaluokan joutuu koodaamaan useaan kertaan, eli tässä:

        1. Swing
        2. AWT
        3. J2ME (esim. javaa tukeviin kännyköihin)

        sama ongelma vaivaa myös HTTP -protokollaa tukevaa omaa luokkaa:

        Siinäkin ilmeisesti joudutaan koodaamaan 2 kertaan, kerran J2ME:lle ja toiseen kertaan koodia, joka sitten ilmeisesti toimii samalla tavalla J2SE:ssä ja J2EE:ssä.

        Asiaa hankaloittaa vielä lisää se, ettei Javassa ole yleispätevää ifdef - else - endif -ehdollista kääntämistä.

        Tuolla nimittäin voisi esim. omassa HTTP -käsittelyluokassa tehdä jotain tämäntapaista:

        {$IFDEF J2SE}
        {$DEFINE J2SE_EE}
        {$ENDIF}

        {$IFDEF J2EE}
        {$DEFINE J2SE_EE}
        {$ENDIF}

        --

        {$IFDEF J2SE_EE}
        // tähän koodia / määritteöyitä joiden avulla luokan toiminnallisuus toteutetaan J2SE ja J2EE -ympäristöissä
        {$ENDIF}

        {$IFDEF J2ME}
        // tähän koodia / määritteöyitä joiden avulla luokan toiminnallisuus toteutetaan J2ME -ympäristössä
        {$ENDIF}

        Kun java ei kuitenkaan yleispätevästi tue ifdef -ehdollista kääntämistä, joudutaan tässäkin ilmeisesti tekemään sama toiminnallisuus useaan kertaan eri ympäristöihin ja mahdollisesti vielä 1 apuluokka, joka osaa itse luod atarvittavien muiden luokkien ilmentymiä sen mukaan, onko mikä javaversio (ME / SE / EE) tai vastaavasti mikä GUI (swing, AWT, J2ME)

        En todellakaan muista, mikä on J2ME:ssä käytetty GUI. mutta jossain kännykän javaohjelmointia käsitelleessä kirjassa tuokin on kerrottu.

        Onko tässä siis tuon TTimer -toiminnallisuudenkin yleispätevästi saadakseen koodattava sama asia 3 kertaan ?

        Vai löytyisikö joku fiksumpi ratkaisu?

        em. linkeistä:

        swing -linkkejä en mielellään käyttäisi, paitsi jos ei ole muuta toimivaa keinoa, syynä juuri se, että niillä saadaan aikaan ratkaisu, joka toimi vain swingissä, ei muissa ympäristöissä.

        ja tuosta java.util.timeristä: toteuttaa vain puolet ratkaisusta eli saadaan säännöllisesti kutsuttava rutiini aikaiseksi, mutta vaatisi tuekseen jotain samantapaista kuin PostMessage() windowsissa.

        Jotain tuossa omassa TTimer -luokassakin olen toki käyttänyt, minnehän sen luokan voisi postata?

        Tänne jos copypastettaa niin ruman näköistähän siitä tulee, kun sisennykset katoavat.


      • javaopiskelija
        javaopiskelija kirjoitti:

        Tuo swing- luokka on yhdessä mielessä todella ikävä:

        Jos ratkaisu tehdään sillä, niin sama työ joudutaan tekemään 3 kertaan:

        1. kerran swing.Timer -luokalla

        2. kerran AWT:n vastaavalla

        ja vielä 3. kerran jollain, mikä toimii J2ME ympäristössä.

        Tämän takia mielellään tekisin homman jollain sellaisella keinolla, joka on kelvollinen sekä swingissä, AWT:ssä että myös J2ME:ssä.

        Olen joskus itse rakentanut javaluokan, joka periaatteessa toimii mahdollisimman samoin kuin Delphin TTimer -luokka (pieniä eroja toki on, johtuen Delphin ja Javan erilaisesta tavasta käsitellä tapahtumakäsittelijöiden hallintaa).

        Mutta tuo oma TTimer -luokka muistaakseni on puutteellinen juuri siksi, että se ratkaisee vain osan ongelmaa:

        Se kyllä kutsuu jotain rutiinia määrävälein, mutta ei mitenkään takaa, mistä säikeestä kutsutaan. Tästä syystä tuo vaatisi muokkausta siten, että joko koko käytetty ajatintyyppi on vaihdettava toiseksi, sellaiseksi joka laukeaa siinä säikeessä, jossa GUI -käsittely on OK, tai sitten se vaatisi tuekseen jotain samantapaista kuin windowsissa on PostMessage.

        Eikö javan pitänyt olla laite- ja käyttöjärjestelmäriippumaton ohjelmointikieli / - väline / -ympäristö ?

        Tämä ei käytännössä toteudu kovinkaan hyvin, jos jokaisen hyödyllisen javaluokan joutuu koodaamaan useaan kertaan, eli tässä:

        1. Swing
        2. AWT
        3. J2ME (esim. javaa tukeviin kännyköihin)

        sama ongelma vaivaa myös HTTP -protokollaa tukevaa omaa luokkaa:

        Siinäkin ilmeisesti joudutaan koodaamaan 2 kertaan, kerran J2ME:lle ja toiseen kertaan koodia, joka sitten ilmeisesti toimii samalla tavalla J2SE:ssä ja J2EE:ssä.

        Asiaa hankaloittaa vielä lisää se, ettei Javassa ole yleispätevää ifdef - else - endif -ehdollista kääntämistä.

        Tuolla nimittäin voisi esim. omassa HTTP -käsittelyluokassa tehdä jotain tämäntapaista:

        {$IFDEF J2SE}
        {$DEFINE J2SE_EE}
        {$ENDIF}

        {$IFDEF J2EE}
        {$DEFINE J2SE_EE}
        {$ENDIF}

        --

        {$IFDEF J2SE_EE}
        // tähän koodia / määritteöyitä joiden avulla luokan toiminnallisuus toteutetaan J2SE ja J2EE -ympäristöissä
        {$ENDIF}

        {$IFDEF J2ME}
        // tähän koodia / määritteöyitä joiden avulla luokan toiminnallisuus toteutetaan J2ME -ympäristössä
        {$ENDIF}

        Kun java ei kuitenkaan yleispätevästi tue ifdef -ehdollista kääntämistä, joudutaan tässäkin ilmeisesti tekemään sama toiminnallisuus useaan kertaan eri ympäristöihin ja mahdollisesti vielä 1 apuluokka, joka osaa itse luod atarvittavien muiden luokkien ilmentymiä sen mukaan, onko mikä javaversio (ME / SE / EE) tai vastaavasti mikä GUI (swing, AWT, J2ME)

        En todellakaan muista, mikä on J2ME:ssä käytetty GUI. mutta jossain kännykän javaohjelmointia käsitelleessä kirjassa tuokin on kerrottu.

        Onko tässä siis tuon TTimer -toiminnallisuudenkin yleispätevästi saadakseen koodattava sama asia 3 kertaan ?

        Vai löytyisikö joku fiksumpi ratkaisu?

        em. linkeistä:

        swing -linkkejä en mielellään käyttäisi, paitsi jos ei ole muuta toimivaa keinoa, syynä juuri se, että niillä saadaan aikaan ratkaisu, joka toimi vain swingissä, ei muissa ympäristöissä.

        ja tuosta java.util.timeristä: toteuttaa vain puolet ratkaisusta eli saadaan säännöllisesti kutsuttava rutiini aikaiseksi, mutta vaatisi tuekseen jotain samantapaista kuin PostMessage() windowsissa.

        Jotain tuossa omassa TTimer -luokassakin olen toki käyttänyt, minnehän sen luokan voisi postata?

        Tänne jos copypastettaa niin ruman näköistähän siitä tulee, kun sisennykset katoavat.

        Kaivoin sitten esille tuon aikanaan tekemäni oman TTimer -luokan.

        Sen toteutuksessa on käytetty juurikin näitä:

        import java.util.TimerTask;
        import java.util.Timer;

        lisäksi olen itse määritellyt tällaisen:

        public interface TTimerEvent
        {
        void TimerXTimer(TTimer Sender);
        }

        Ja em. TTimer -luokassa on sitten mm. tällaisia:

        public class TTimer extends TimerTask {

        private boolean FRunning = false;
        private boolean FEnabled = false;

        private int FInterval = 0;
        private TTimerEvent FOnTimer = null;

        private Timer myTimer = null;
        public String Name;

        // ja tuo delphi -tyylinen OnTimer -toiminnallisuus on tehty näin:

        public void run() {
        if ((FRunning && FEnabled) && (FOnTimer != null) ) {
        //
        FOnTimer.TimerXTimer(this);
        }
        }
        }

        Jos verrataan Delphin TTimeriin niin tekemäni TTimer javalle kärsii tosiaan muutamasta ongelmasta:

        1. Kutsuu TimerXTimer -metodia säikeestä, joka EI ole se, josta GUI -päivitykset olisivat turvallisia.

        onko javassa joku windowsin PostMessage():a vastaava mekanismi, jolla tuossa ajastinluokassa (jonka ajastinliipaisumetdia kutsutaan "vieraasta" säikeestä) voisi tehdä jotain PostMessage():n tapaista ja sitten GUI -luokassa (lomake) käsitellä nämä viestit.

        Kai tuohon joku tapa pitäisi löytyä, sillä jotenkinhan esim Button -painalluskin saadaan kutsumaan GUI -luokan käsittelijää. Miten saman mekanismin saisi itse liipaistua, mutta niin, että liipaisu tapahtuu GUI -turvalölisesta säikeestä kuten esim. mainittu Button -käsittelijäkin ?


        2. Koska javassa ei ole (tai jos on, kertokaapa miten!) Delphi -tyylisiä tapahtumakäsittelijöitä, on niitä simuloitu TTimerEvent -interface:lla.

        Ratkaisu kyllä toimii, mutta esim graafiselle lomakkeelle voi näin määritellä vain yhden Timer -käsittelijän. Lomakkeelle voi toki laittaa useampia TTimer -komponentteja, mutta ne kaikki kutsuvat samaa tapahtumakäsittelijää, mikä sitten johtaisi lomakkeella tämäntapaiseen koodiin:

        public void TimerXTimer(TTimer Sender) {

        if (Sender == Timer1) { Timer1Timer(Sender) };
        if (Sender == tmrClockUpd) { tmrClockUpdTimer(Sender) };
        if (Sender == tmrHttpReadyChk) { tmrHttpReadyChkTimer(Sender) };
        if (Sender == tmrFancy) { tmrFancyTimer(Sender) };

        }


      • javaopiskelija
        javaopiskelija kirjoitti:

        Tuo swing- luokka on yhdessä mielessä todella ikävä:

        Jos ratkaisu tehdään sillä, niin sama työ joudutaan tekemään 3 kertaan:

        1. kerran swing.Timer -luokalla

        2. kerran AWT:n vastaavalla

        ja vielä 3. kerran jollain, mikä toimii J2ME ympäristössä.

        Tämän takia mielellään tekisin homman jollain sellaisella keinolla, joka on kelvollinen sekä swingissä, AWT:ssä että myös J2ME:ssä.

        Olen joskus itse rakentanut javaluokan, joka periaatteessa toimii mahdollisimman samoin kuin Delphin TTimer -luokka (pieniä eroja toki on, johtuen Delphin ja Javan erilaisesta tavasta käsitellä tapahtumakäsittelijöiden hallintaa).

        Mutta tuo oma TTimer -luokka muistaakseni on puutteellinen juuri siksi, että se ratkaisee vain osan ongelmaa:

        Se kyllä kutsuu jotain rutiinia määrävälein, mutta ei mitenkään takaa, mistä säikeestä kutsutaan. Tästä syystä tuo vaatisi muokkausta siten, että joko koko käytetty ajatintyyppi on vaihdettava toiseksi, sellaiseksi joka laukeaa siinä säikeessä, jossa GUI -käsittely on OK, tai sitten se vaatisi tuekseen jotain samantapaista kuin windowsissa on PostMessage.

        Eikö javan pitänyt olla laite- ja käyttöjärjestelmäriippumaton ohjelmointikieli / - väline / -ympäristö ?

        Tämä ei käytännössä toteudu kovinkaan hyvin, jos jokaisen hyödyllisen javaluokan joutuu koodaamaan useaan kertaan, eli tässä:

        1. Swing
        2. AWT
        3. J2ME (esim. javaa tukeviin kännyköihin)

        sama ongelma vaivaa myös HTTP -protokollaa tukevaa omaa luokkaa:

        Siinäkin ilmeisesti joudutaan koodaamaan 2 kertaan, kerran J2ME:lle ja toiseen kertaan koodia, joka sitten ilmeisesti toimii samalla tavalla J2SE:ssä ja J2EE:ssä.

        Asiaa hankaloittaa vielä lisää se, ettei Javassa ole yleispätevää ifdef - else - endif -ehdollista kääntämistä.

        Tuolla nimittäin voisi esim. omassa HTTP -käsittelyluokassa tehdä jotain tämäntapaista:

        {$IFDEF J2SE}
        {$DEFINE J2SE_EE}
        {$ENDIF}

        {$IFDEF J2EE}
        {$DEFINE J2SE_EE}
        {$ENDIF}

        --

        {$IFDEF J2SE_EE}
        // tähän koodia / määritteöyitä joiden avulla luokan toiminnallisuus toteutetaan J2SE ja J2EE -ympäristöissä
        {$ENDIF}

        {$IFDEF J2ME}
        // tähän koodia / määritteöyitä joiden avulla luokan toiminnallisuus toteutetaan J2ME -ympäristössä
        {$ENDIF}

        Kun java ei kuitenkaan yleispätevästi tue ifdef -ehdollista kääntämistä, joudutaan tässäkin ilmeisesti tekemään sama toiminnallisuus useaan kertaan eri ympäristöihin ja mahdollisesti vielä 1 apuluokka, joka osaa itse luod atarvittavien muiden luokkien ilmentymiä sen mukaan, onko mikä javaversio (ME / SE / EE) tai vastaavasti mikä GUI (swing, AWT, J2ME)

        En todellakaan muista, mikä on J2ME:ssä käytetty GUI. mutta jossain kännykän javaohjelmointia käsitelleessä kirjassa tuokin on kerrottu.

        Onko tässä siis tuon TTimer -toiminnallisuudenkin yleispätevästi saadakseen koodattava sama asia 3 kertaan ?

        Vai löytyisikö joku fiksumpi ratkaisu?

        em. linkeistä:

        swing -linkkejä en mielellään käyttäisi, paitsi jos ei ole muuta toimivaa keinoa, syynä juuri se, että niillä saadaan aikaan ratkaisu, joka toimi vain swingissä, ei muissa ympäristöissä.

        ja tuosta java.util.timeristä: toteuttaa vain puolet ratkaisusta eli saadaan säännöllisesti kutsuttava rutiini aikaiseksi, mutta vaatisi tuekseen jotain samantapaista kuin PostMessage() windowsissa.

        Jotain tuossa omassa TTimer -luokassakin olen toki käyttänyt, minnehän sen luokan voisi postata?

        Tänne jos copypastettaa niin ruman näköistähän siitä tulee, kun sisennykset katoavat.

        Kaivoin sitten esiin myös aikanaan tekemäni GUI -testiohjelman, ja hämmästyin!

        Eikös AWT ja Swing pitäisi olla keskenään vaihtoehtoisia GUI -kirjastoja javalle ?

        kuitenkin GUI -modulistani löytyy seuraavaa:

        private javax.swing.JButton bnClose;

        mutta toisaalta myös:

        private void bnCloseActionPerformed(java.awt.event.ActionEvent evt) {

        System.extit(0);
        }

        siis javax.swing.JButton -tyyppiä oleva bnClose, mutta sen käsittelijässä java.awt.event.ActionEvent -tyyppinen evt -parametri ?

        Onko tuossa nyt jotenkin saatu sotketuksi swingiä ja awt:tä keskenään vai miksi näin ???

        Tuon tekemisessä on käytetty NetBeans 5.5 IDE:ä.

        Jahka saan linux -versioni päivitettyä, ehkäpä pitäisi etsiä ja asentaa jostain tuoreempi NetBeans?


      • javaopiskelija
        javaopiskelija kirjoitti:

        Kaivoin sitten esille tuon aikanaan tekemäni oman TTimer -luokan.

        Sen toteutuksessa on käytetty juurikin näitä:

        import java.util.TimerTask;
        import java.util.Timer;

        lisäksi olen itse määritellyt tällaisen:

        public interface TTimerEvent
        {
        void TimerXTimer(TTimer Sender);
        }

        Ja em. TTimer -luokassa on sitten mm. tällaisia:

        public class TTimer extends TimerTask {

        private boolean FRunning = false;
        private boolean FEnabled = false;

        private int FInterval = 0;
        private TTimerEvent FOnTimer = null;

        private Timer myTimer = null;
        public String Name;

        // ja tuo delphi -tyylinen OnTimer -toiminnallisuus on tehty näin:

        public void run() {
        if ((FRunning && FEnabled) && (FOnTimer != null) ) {
        //
        FOnTimer.TimerXTimer(this);
        }
        }
        }

        Jos verrataan Delphin TTimeriin niin tekemäni TTimer javalle kärsii tosiaan muutamasta ongelmasta:

        1. Kutsuu TimerXTimer -metodia säikeestä, joka EI ole se, josta GUI -päivitykset olisivat turvallisia.

        onko javassa joku windowsin PostMessage():a vastaava mekanismi, jolla tuossa ajastinluokassa (jonka ajastinliipaisumetdia kutsutaan "vieraasta" säikeestä) voisi tehdä jotain PostMessage():n tapaista ja sitten GUI -luokassa (lomake) käsitellä nämä viestit.

        Kai tuohon joku tapa pitäisi löytyä, sillä jotenkinhan esim Button -painalluskin saadaan kutsumaan GUI -luokan käsittelijää. Miten saman mekanismin saisi itse liipaistua, mutta niin, että liipaisu tapahtuu GUI -turvalölisesta säikeestä kuten esim. mainittu Button -käsittelijäkin ?


        2. Koska javassa ei ole (tai jos on, kertokaapa miten!) Delphi -tyylisiä tapahtumakäsittelijöitä, on niitä simuloitu TTimerEvent -interface:lla.

        Ratkaisu kyllä toimii, mutta esim graafiselle lomakkeelle voi näin määritellä vain yhden Timer -käsittelijän. Lomakkeelle voi toki laittaa useampia TTimer -komponentteja, mutta ne kaikki kutsuvat samaa tapahtumakäsittelijää, mikä sitten johtaisi lomakkeella tämäntapaiseen koodiin:

        public void TimerXTimer(TTimer Sender) {

        if (Sender == Timer1) { Timer1Timer(Sender) };
        if (Sender == tmrClockUpd) { tmrClockUpdTimer(Sender) };
        if (Sender == tmrHttpReadyChk) { tmrHttpReadyChkTimer(Sender) };
        if (Sender == tmrFancy) { tmrFancyTimer(Sender) };

        }

        Itselleni on siis tärkein tuo J2ME eli matkapuhelimien javaohjelmointi.

        Mutta koska J2ME -ohjelman debuggaus (ainakin NetBeans 5.5:llä) on huomattavasti hankalampaa kuin J2SE -ohjelman, niin siksi mielelläni tekisin kaikista ohjelmista 2 versiota:

        1. J2ME matkapuhelimiin JA
        2. J2SE PC:lle

        Tuon J2SE:n osalta en tiedä, kumpi olisi tarkoituksiini parempi, Swing vai AWT.

        Mutta tärkeimpänä valintaperusteena Swingin ja AWT:n välillä pitäisin sitä, että kummassa säieturvallisuus toimii mahdollisimman lähellä samaa tapaa, jota J2ME -ohjelmissa käytetään.

        J2ME:ssähän on sitten MIDP ja CLDC.

        Eli lopullisena tavoitteenani on tehdä nimenomaan J2ME/MIDP/CLDC -ohjelmia, mutta niiden hankalan debugattavuuden takia olsi hyvä jos saisi tehtyä ohjelmasta myös J2SE -version (olipa siinä sitten käytetty Swingiä tai AWT:tä), niin mahdollisten virheiden etsintä ja korjaus olisi huomattavasti helpompaa.

        Jos muistan oikein, niin J2ME -ohjelmien debuggaus turhan helposti jumittaa koko NetBeand IDE:n.

        Lisäksi, jos haluaa testi- ja debuggaustarkoituksessa tulostaa jotain näytölle niin J2SE -ohjelmassa näytöllä on paljon enemmän tilaa kuin J2ME -ohjelmassa.


      • javaopiskelija
        javaopiskelija kirjoitti:

        Kaivoin sitten esiin myös aikanaan tekemäni GUI -testiohjelman, ja hämmästyin!

        Eikös AWT ja Swing pitäisi olla keskenään vaihtoehtoisia GUI -kirjastoja javalle ?

        kuitenkin GUI -modulistani löytyy seuraavaa:

        private javax.swing.JButton bnClose;

        mutta toisaalta myös:

        private void bnCloseActionPerformed(java.awt.event.ActionEvent evt) {

        System.extit(0);
        }

        siis javax.swing.JButton -tyyppiä oleva bnClose, mutta sen käsittelijässä java.awt.event.ActionEvent -tyyppinen evt -parametri ?

        Onko tuossa nyt jotenkin saatu sotketuksi swingiä ja awt:tä keskenään vai miksi näin ???

        Tuon tekemisessä on käytetty NetBeans 5.5 IDE:ä.

        Jahka saan linux -versioni päivitettyä, ehkäpä pitäisi etsiä ja asentaa jostain tuoreempi NetBeans?

        Jaahas... pikainen tutkimus netistä paljastaa seuraavaa:

        lainaus IBM:n javaa käsittelevältä sivulta:

        http://www.ibm.com/developerworks/grid/library/os-swingswt/

        "AWT components are thread-safe, which means you do not need to be concerned as to which thread in your application updates the GUI. This can eliminate many GUI update problems, but can make AWT GUIs run slower."

        Koska itse haluan tehdä javalla PC -ohjelmia vain rinnakkaisversioksi J2ME -ohjelmille ja debuggaus- ja testitarkoituksiin, niin tämä huomioonottaen oma valintani taitaakin olla tuolla ratkaistu:

        Mahdollinen hieman hitaampi GUI -liittymän toiminta on pieni hinta siitä, että voin ilmeisesti J2SE:ssä unohtaa koko säieongelman, sillä tuossahan luvataan, että

        "AWT components are thread-safe, which means you do not need to be concerned as to which thread in your application updates the GUI"

        Eli tämä puoltaisi AWT:n käyttöä ja Swingin hylkäämistä.

        J2SE -ohjelmien osalta ongelma olisi ilmeisesti tuolla ratkaistu.

        Mutta entäpä J2ME/MIDP/CLDC ?

        Voiko siellä käyttöliittymää päivittää mistä säikeestä tahansa?

        Jos ei, niin sitä varten joudutaan joka tapauksessa etsimään ratkaisu samaan ongelmaan.

        Miten ?


      • javaopiskelija
        javaopiskelija kirjoitti:

        Jaahas... pikainen tutkimus netistä paljastaa seuraavaa:

        lainaus IBM:n javaa käsittelevältä sivulta:

        http://www.ibm.com/developerworks/grid/library/os-swingswt/

        "AWT components are thread-safe, which means you do not need to be concerned as to which thread in your application updates the GUI. This can eliminate many GUI update problems, but can make AWT GUIs run slower."

        Koska itse haluan tehdä javalla PC -ohjelmia vain rinnakkaisversioksi J2ME -ohjelmille ja debuggaus- ja testitarkoituksiin, niin tämä huomioonottaen oma valintani taitaakin olla tuolla ratkaistu:

        Mahdollinen hieman hitaampi GUI -liittymän toiminta on pieni hinta siitä, että voin ilmeisesti J2SE:ssä unohtaa koko säieongelman, sillä tuossahan luvataan, että

        "AWT components are thread-safe, which means you do not need to be concerned as to which thread in your application updates the GUI"

        Eli tämä puoltaisi AWT:n käyttöä ja Swingin hylkäämistä.

        J2SE -ohjelmien osalta ongelma olisi ilmeisesti tuolla ratkaistu.

        Mutta entäpä J2ME/MIDP/CLDC ?

        Voiko siellä käyttöliittymää päivittää mistä säikeestä tahansa?

        Jos ei, niin sitä varten joudutaan joka tapauksessa etsimään ratkaisu samaan ongelmaan.

        Miten ?

        Ainakin tällä sivulla olevan esimerkin:

        http://developers.sun.com/mobility/midp/articles/threading/

        ... perusteella näyttäisi siltä, että myös J2ME:ssä näytön päivityksen saa tehdä "vieraasta" säikeestä.

        Eikö seuraava koodinpätkä tee juuri näin (kutsuu näytön päivitystä TimerTask/Run -metodista):

        public WaitCanvas() {
        mCount = 0;
        mMaximum = 36;
        mInterval = 100;

        mWidth = getWidth();
        mHeight = getHeight();

        // Calculate the radius.
        int halfWidth = (mWidth - mRadius) / 2;
        int halfHeight = (mHeight - mRadius) / 2;
        mRadius = Math.min(halfWidth, halfHeight);

        // Calculate the location.
        mX = halfWidth - mRadius / 2;
        mY = halfHeight - mRadius / 2;

        // Create a Timer to update the display.
        TimerTask task = new TimerTask() {
        public void run() {
        mCount = (mCount 1) % mMaximum;
        repaint();
        }
        };
        Timer timer = new Timer();
        timer.schedule(task, 0, mInterval);
        }


      • fidel1
        javaopiskelija kirjoitti:

        Tuo swing- luokka on yhdessä mielessä todella ikävä:

        Jos ratkaisu tehdään sillä, niin sama työ joudutaan tekemään 3 kertaan:

        1. kerran swing.Timer -luokalla

        2. kerran AWT:n vastaavalla

        ja vielä 3. kerran jollain, mikä toimii J2ME ympäristössä.

        Tämän takia mielellään tekisin homman jollain sellaisella keinolla, joka on kelvollinen sekä swingissä, AWT:ssä että myös J2ME:ssä.

        Olen joskus itse rakentanut javaluokan, joka periaatteessa toimii mahdollisimman samoin kuin Delphin TTimer -luokka (pieniä eroja toki on, johtuen Delphin ja Javan erilaisesta tavasta käsitellä tapahtumakäsittelijöiden hallintaa).

        Mutta tuo oma TTimer -luokka muistaakseni on puutteellinen juuri siksi, että se ratkaisee vain osan ongelmaa:

        Se kyllä kutsuu jotain rutiinia määrävälein, mutta ei mitenkään takaa, mistä säikeestä kutsutaan. Tästä syystä tuo vaatisi muokkausta siten, että joko koko käytetty ajatintyyppi on vaihdettava toiseksi, sellaiseksi joka laukeaa siinä säikeessä, jossa GUI -käsittely on OK, tai sitten se vaatisi tuekseen jotain samantapaista kuin windowsissa on PostMessage.

        Eikö javan pitänyt olla laite- ja käyttöjärjestelmäriippumaton ohjelmointikieli / - väline / -ympäristö ?

        Tämä ei käytännössä toteudu kovinkaan hyvin, jos jokaisen hyödyllisen javaluokan joutuu koodaamaan useaan kertaan, eli tässä:

        1. Swing
        2. AWT
        3. J2ME (esim. javaa tukeviin kännyköihin)

        sama ongelma vaivaa myös HTTP -protokollaa tukevaa omaa luokkaa:

        Siinäkin ilmeisesti joudutaan koodaamaan 2 kertaan, kerran J2ME:lle ja toiseen kertaan koodia, joka sitten ilmeisesti toimii samalla tavalla J2SE:ssä ja J2EE:ssä.

        Asiaa hankaloittaa vielä lisää se, ettei Javassa ole yleispätevää ifdef - else - endif -ehdollista kääntämistä.

        Tuolla nimittäin voisi esim. omassa HTTP -käsittelyluokassa tehdä jotain tämäntapaista:

        {$IFDEF J2SE}
        {$DEFINE J2SE_EE}
        {$ENDIF}

        {$IFDEF J2EE}
        {$DEFINE J2SE_EE}
        {$ENDIF}

        --

        {$IFDEF J2SE_EE}
        // tähän koodia / määritteöyitä joiden avulla luokan toiminnallisuus toteutetaan J2SE ja J2EE -ympäristöissä
        {$ENDIF}

        {$IFDEF J2ME}
        // tähän koodia / määritteöyitä joiden avulla luokan toiminnallisuus toteutetaan J2ME -ympäristössä
        {$ENDIF}

        Kun java ei kuitenkaan yleispätevästi tue ifdef -ehdollista kääntämistä, joudutaan tässäkin ilmeisesti tekemään sama toiminnallisuus useaan kertaan eri ympäristöihin ja mahdollisesti vielä 1 apuluokka, joka osaa itse luod atarvittavien muiden luokkien ilmentymiä sen mukaan, onko mikä javaversio (ME / SE / EE) tai vastaavasti mikä GUI (swing, AWT, J2ME)

        En todellakaan muista, mikä on J2ME:ssä käytetty GUI. mutta jossain kännykän javaohjelmointia käsitelleessä kirjassa tuokin on kerrottu.

        Onko tässä siis tuon TTimer -toiminnallisuudenkin yleispätevästi saadakseen koodattava sama asia 3 kertaan ?

        Vai löytyisikö joku fiksumpi ratkaisu?

        em. linkeistä:

        swing -linkkejä en mielellään käyttäisi, paitsi jos ei ole muuta toimivaa keinoa, syynä juuri se, että niillä saadaan aikaan ratkaisu, joka toimi vain swingissä, ei muissa ympäristöissä.

        ja tuosta java.util.timeristä: toteuttaa vain puolet ratkaisusta eli saadaan säännöllisesti kutsuttava rutiini aikaiseksi, mutta vaatisi tuekseen jotain samantapaista kuin PostMessage() windowsissa.

        Jotain tuossa omassa TTimer -luokassakin olen toki käyttänyt, minnehän sen luokan voisi postata?

        Tänne jos copypastettaa niin ruman näköistähän siitä tulee, kun sisennykset katoavat.

        No, koetetaanpa koota tähän vastauksia kysymyksiisi..

        Juu, javasta löytyy eri käyttöliittymäkirjastoja eri ympäristöihin. Niinkuin varmasti kaikista muistakin kielista (siis tämähän ei ole kielen ominaisuus vaan käytettyjen kirjastojen). Varsinkin mobiilialustoille vain joutuu tekemään omat versiot käyttöliittymistä, sille ei voi mitään. Ei toi sun PostMessage-härpäkekkään varmasti toimi Symbianissa.

        AWT on vanha, alkuperäinen käyttöliittymäkirjasto, joka käyttää alustan natiiveja komponentteja -> ei siis ole saman näköinen kaikilla alustoilla. Swing korjaa tämän, eli Swingillä kirjoitetut ohjelmat näyttävät ja toimivat samoin kaikilla Swingiä tukevilla alustoilla. Se, että Swingissä käytetään joitain java.awt.*-paketeissa määritettyjä luokkia ei tarkoita, että nämä olisi jotenkin "sekoitettu" keskenään. Esim. tapahtumien käsittely on toteutettu awt:ssä riittävän hyvin, sitä on turha tehdä "uudestaan" swingiä varten. AWT:tä ei ole tarvetta enää käyttää normaaleilla alustoilla, Swing on käytännössä korvannut sen. Mitään säieongelmia ei Swing-ohjelmissa ole, jos opettelee käyttämään Swingin säikeitä oikein.

        Tuota IFDEF-höpötystä olet muistaakseni aikaisemminkin tänne suoltanut ja vastaus on edelleen rajapinnat. Luot rajapinnan, joka piilottaa varsinaisen käytetyn kirjaston toteutukseltasi. Näin pääohjelmaasi ei tarvitse muuttaa eri ympäristöissä, sillä kun ei ole mitään tietoa, minkä kirjaston palveluja se todella käyttää.

        J2ME-sovellusten debuggaus J2SE-ympäristössä kuulostaa kyllä aika oudolta. Ehkä jotain background-rutiineja voisikin debugata, mutta käyttöliittymän debuggauksesta ei varmastikaan ole paljoa hyötyä, sen verran erilaisista ympäristöistä on kyse. En ole itse koskaan tehnyt mitään J2ME-alustalla, mutta sitä varten on käsittääkseni olemassa omat kehitysympäristöt. Taisi olla ainakin Nokia, jolta sai Eclipsen päällä pyörivän emulaattori/debuggerin.


    Ketjusta on poistettu 0 sääntöjenvastaista viestiä.

    Luetuimmat keskustelut

    1. Huomenna teen sen

      Se on nyt päätetty. Pääsen pois tästä epätietosuudesta.
      Ikävä
      52
      1707
    2. Hakkarainen: persut Venäjän ja Pohjois-Korean tiellä

      Hakkarainen entisenä persujen kärkipoliitikkona tietää, mitä puhuu. https://www.is.fi/politiikka/art-2000010422614.html
      Maailman menoa
      173
      1522
    3. Fuengirola.fi: Kohuissa rypenyt Jari Sillanpää, 58, harvinaisessa haastattelussa: "Minä haluan..."

      Ex-tangokuningas on kertonut kuulumisiaan Espanjan Aurinkorannikolta. Että ei muuta kuin elämässä etiäpäin, Jari Sillanp
      Kotimaiset julkkisjuorut
      20
      1062
    4. Ilouutinen! Anniina Valtonen heitti jymy-yllätyksen - Tämä ei jätä kylmäksi!

      Ohhoh, tämäpä ylläri! Anniina Valtonen sai puolisonsa kanssa lapsen viime vuoden lopulla. Lue lisää: https://www.suomi2
      Suomalaiset julkkikset
      9
      963
    5. Ootko muuten vieläkään hiffannut

      Että en kuulu sinun maailmaasi? On meissä samaa, ja samaa aaltopituutta oli, mutta tunsin oloni usein hyvin vaivautuneek
      Ikävä
      116
      881
    6. Susta on tullut

      Ihana nainen. ❤️
      Ikävä
      48
      789
    7. Miten nyt sanoisin

      tämän sinulle. Oletko mielessäni päivittäin, kysyin itseltäni ja vastaus oli, kyllä olet. Yllätyin, päädyin oudoille tei
      Ikävä
      39
      758
    8. Voitko vain unohtaa

      Minut. En ole sinun arvoisesi
      Ikävä
      55
      641
    9. Tämä ei voi jatkua

      Näin. Eilisen jälkeen tulin siihen tulokseen.
      Ikävä
      53
      619
    10. Oletko joskus pieni ja haavoittuva

      vai oletko aina vahva, miltä aina vaikutat? Nainen, oletko koskaan väsynyt ja haavoilla? Yritätkö silti pitää julkisivua
      Ikävä
      51
      618
    Aihe