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ä.
TTimer ja GUI
10
737
Vastaukset
- 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
Ja taas ammuttu kokkolassa
Kokkolaisilta pitäisi kerätä pois kaikki ampumaset, keittiöveitset ja kaikki mikä vähänkään paukku ja on terävä.726348- 1385772
Helena Koivu on äiti
Mitä hyötyä on Mikko Koivulla kohdella LASTENSA äitiä huonosti . Vie lapset tutuista ympyröistä pois . Lasten kodista.4863654Ovatko naiset lopettaneet sen vähäisenkin vaivannäön Tinderissa?
Meinaan vaan profiileja selatessa nykyään valtaosalla ei ole minkäänlaista kirjoitettua tekstiä siellä. Juuri ja juuri s1202059- 391361
Suomi vietiin Natoon väärin perustein. Viides artikla on hölynpölyä. Yksin jäämme.
Kuka vielä uskoo, että viides artikla takaa Suomelle avun, jos Suomeen hyökätään. Liikuttavasti täällä on uskottu ja ved4021345- 731173
Sydämeni on sinun luona
Koko ajan. Oli ympärilläni ketä oli niin sinä olet vain ajatuksissa ja tunteissa. En halua muiden kosketusta kuin sinun471034Trump ja Venäjä
Huomasitteko muuten... Käytännössä ainoat valtiot, joille Trump EI eilen asettanut typeriä tariffejaan, olivat Venäjä ja110952Jatkuva stressitila
On sinun vuoksesi kun en tiedä missä mennään mutta tunteeni tiedän ainoastaan56950