StringGrid
StringGrid
on TableView
-komponentista peritty komponentti, jonka tarkoitus on helpottaa taulukkomuotoisen aineiston käsittelyä.
Merkittävä ero TableView
-komponenttiin on se, että alkioihin pääsee helposti käsiksi rivi- ja sarakeindeksin avulla. Rivi- ja sarakeindeksi ovat indeksejä alkueräiseen lajittelemattomaan taulukkoon nähden. Lisäksi kunkin solun ulkoasua voi säätää helposti erikseen.
Jar-tiedoston hakeminen: fxgui.jar.
1. Käyttö suunnitteluaikana
Ohjelman ulkoasun suunnitteluaikana voi StringGrid
-komponenttiin lisätä malliaineistoa laittamalla Rivit
-ominaisuuteen tekstiä tyyliin:
ala|aloitusvuosi|h/vko
kalastus|1955|20
laiskottelu|1950|20
työn pakoilu|1952|40
Katso tarkemmin SceneBuilderin esimerkistä.
2. Yleisimpiä toimintoja
Kaikki (tai ainakin suurin osa) TableView-komponentin ominaisuuksista toimii.
Merkintä (SC) alla tarkoittaa että ominaisuuden voi valita myös SceneBuilderissä. Esimerkeissä taulukon nimi vaihtelee sen mukaan mistä ohjelmasta koodinpala on kopioitu.
2.1 Sarakkeiden luominen
Mikäli sarakemäärä on saatu oikeaksi ja otsikot ovat oikeita jo suunnitteluaikana, ei tässä kohti tarvitse tehdä muuta.
Mikäli sarakemäärää halutaan muuttaa, täytyy koko talukko luoda (toistaiseki) uudelleen.
Luodaan esimerkiksi RistiNollaa varten sarakkeet, joissa 1. otsikko on tyhjä ja muissa juokseva numero:
String[] headings = new String[koko+1];
headings[0] = "";
for (int i=1; i<=koko; i++) headings[i] = ""+i;
grid.initTable(headings);
Tämä tyhjentää kaikki asetukset, eli on tehtävä ennen muita rivi-/sarakeasetuksia.
2.2 Yleisiä asetuksia
2.3 Rivien lisääminen
Alkion ja sen näkyvien tietojen lisääminen:
private void naytaHarrastus(Harrastus har) {
int kenttia = har.getKenttia();
String[] rivi = new String[kenttia-har.ekaKentta()];
for (int i=0, k=har.ekaKentta(); k < kenttia; i++, k++)
rivi[i] = har.anna(k);
tableHarrastukset.add(har,rivi);
}
Tällöin itse taulukko pitää olla esiteltynä tallentamaan vastaavia olioita:
2.3.1 Pelkkien olioiden lisääminen
Voidaan lisätä myös olioita ilman vastaavia merkkijonoja:
Tällöin ei enää toimi grid.get(r,c)
. Ja jotta mitään näkyisi, pitää taulukolle kertoa mistä saadaan kutakin alkiota (rivi, r
, sarake c
) kohti olion vastaavan kentän sisältö merkkijonona.
Tämä tehdään lisäämällä tapahtumankäsittelijolio, joka palautta tiedon siitä, mitä sisältöä soluun pitää näyttää. Usein tässä oikaistaan tekemällä tätä varten lambda-lauseke tyyliin:
Tätä funktiota StringGrid-olio kutsuu jokaiselle taulukon solulle erikseen. Solun näyttämistapahtumalle tulee siis parametrina (edellisillä nimillä):
g
= grid jonka solun arvo tarvitaanjasen
= olio joka liitetty ko rivilledefValue
= oletus solun sisällöller
= row, eli rivin indeksi, solulle jonka sisältö halutaanc
= column, eli sarakkeen indeksi solule, jonka sisältö halutaan
Aina tapahtuman käsitelyssä ei tarvitse käyttää kaikkia parametreja. Esimerkiksi jos tieto saadaan oliosta itsestään, kuten edellä, riittää pyytää oliolta tieto, että mikä arvo laitetaan oliota vastaavan rivin soluun paikassa c
.
Olioita voi lisätä kerrallaan yhden tai kokonaisen tietorakenteen:
Mikäli tämän lisäksi halutaan lajitella sarakkeita muuhun järjestykseen kuin merkkijonojärjestykseen (esimerkiksi hetujen vuoden perusteella), täytyy myös sanoa miten saadaan lajittelussa käytettävä merkkijono. Numeerisen järjestyksen saa sillä että ilmoittaa sarakkeen numeeriseksi.
Esimerkiksi:
2.4 Solun arvon muuttaminen ja katsominen
2.5 Tyhjät solut
2.6 Solujen värit
Solujen väreihin voidaan vaikuttaa .css
-tyyleillä. Halutut tyylit tehdään .css
-tiedostoon ja itse koodiin voidaan sitten laittaa esimerkiksi:
grid.setStyleClass("virhe,sininen", 1, 1);
grid.setStyleClass("s1", 0, 0);
grid.setStyleClass("s2", 1, 0);
grid.setStyleClass("s3", 2, 0);
Rivi- ja sarakeindeksit ovat solujen alkuperäisen sijainnin mukaan riippumatta onko rivejä tai sarakkeita järjestelty uudelleen.
2.7 Solun klikkauksen kuunteleminen
2.9 Solujen muokkaus
Jotta soluja voidaan muokata "lennossa", pitää tämä ilmoittaa taulukolle:
grid.setEditable(true);
Sitten mikäli halutaan muokatulle solulle tehdä jotakin tarkistuksia niin pitää tehdä takaisinkutsu tyyliin:
grid.setOnGridLiveEdit((g, jasen, defValue, r, c, edit) -> {
String virhe = jasen.aseta(c+eka,defValue);
if ( virhe == null ) {
kerho.korvaaTaiLisaa(jasen); // jotta saadaan muutos
edit.setStyle(null);
Dialogs.setToolTipText(edit,"");
} else {
edit.setStyle("-fx-background-color: red");
Dialogs.setToolTipText(edit,virhe);
}
return defValue;
});
Huomioi tuo return lause - heittää hämärähkön virheilmoituksen ilman sitä
—3. Käyttöesimerkkejä
Seuraavana muutamia esimerkkiohjelmia tai niiden osia, joissa on käytetty StringGrid
in ominaisuuksia.
Kaikki esimerkit saa ehkä helpoiten Eclipse-käyttöön
kloonata gitlabista:
https://gitlab.jyu.fi/tie/ohj2/esimerkit/fxexamples/-/tree/master/Examples/src
3.1 RistiNolla
Ristinolla on yksinkertainen esimerkki RistiNolla.pelistä, missä solua klikkaamalla siiten tulee vuoroin X ja vuoroin O. Tässä myös eri solun väri vaihtuu. Vuorossa olevan pelaajan merkki näkyy taulukon vasemassa yläkulmassa.
Pelaaminen valmiista .jar
-tiedostosta:
lataa Examples.jar
komentoirivltä:
jw Examples.jar
3.2 Nimi ja vuosi
Esimerkki uudemman StringGridin käytöstä. Tässä on vain tarkoitus esitellä eri ominaisuuksia. Ominaisuuksia pitää katsoa yksittäisinä eikä niitä ole kaikkia pakko käyttää.
Kun muokataan numerosolua, niin se tulee punaiseksi jos jono ei vastaa kokonaislukua. Esimerkissä on aluksi asetettu yksi solu muuten vaan punaiseksi. Kun soluja klikataan, niistä lähtee väri pois. Muokatun solun jälkeen näytetään oikeassa reunassa muokatun solun arvo ja koordinaatti.
Ajaminen valmiista .jar
-tiedostosta:
- lataa Examples.jar
- komentoirivltä:
java -cp Examples.jar stringgrid.NimiJaVuosiMain
3.3 Kerhon harrastukset
Alla tärkeimmät muutokset harrastusten näyttämiseksi. Esimerkissä kunkin harrastuksen tiedot laitetaan ensin merkkijonotaulukkoon, joka lisätään StringGridin riviksi (metodi naytaHarrastus
).
public class KerhoGUIController implements Initializable {
...
@FXML private StringGrid<Harrastus> tableHarrastukset;
...
protected void alusta() {
...
tableHarrastukset.setPlaceholder(new Label("Ei vielä harrastuksia"));
// alustetaan hrrustustaulukon otsikot
int eka = apuharrastus.ekaKentta();
int lkm = apuharrastus.getKenttia();
String[] headings = new String[lkm-eka];
for (int i=0, k=eka; k<lkm; i++, k++) headings[i] = apuharrastus.getKysymys(k);
tableHarrastukset.initTable(headings);
tableHarrastukset.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
tableHarrastukset.setEditable(false);
// Tämä on vielä huono, ei automaattisesti muutu jos kenttiä muutetaan.
tableHarrastukset.setColumnSortOrderNumber(1);
tableHarrastukset.setColumnSortOrderNumber(2);
tableHarrastukset.setColumnWidth(1, 60);
tableHarrastukset.setColumnWidth(2, 60);
}
...
private void naytaHarrastukset(Jasen jasen) {
tableHarrastukset.clear();
if ( jasen == null ) return;
try {
List<Harrastus> harrastukset = kerho.annaHarrastukset(jasen);
if ( harrastukset.size() == 0 ) return;
for (Harrastus har: harrastukset)
naytaHarrastus(har);
} catch (SailoException e) {
// naytaVirhe(e.getMessage());
}
}
private void naytaHarrastus(Harrastus har) {
int kenttia = har.getKenttia();
String[] rivi = new String[kenttia-har.ekaKentta()];
for (int i=0, k=har.ekaKentta(); k < kenttia; i++, k++)
rivi[i] = har.anna(k);
tableHarrastukset.add(har,rivi);
}
...
private void naytaJasen() {
jasenKohdalla = listJasenet.getSelectionModel().getSelectedItem();
if (jasenKohdalla == null) return;
JasenDialogController.naytaJasen(edits, jasenKohdalla);
naytaHarrastukset(jasenKohdalla);
}
...
}
3.4 Esimerkki: Jäsenen muokkaus StringGridissä
Tässä esimerkissä on tehty kokonainen ohjelma jossa on esimerkki jäsenten muokkaamiseksi StringGridissä
. Esimerkissä ei lisätä merkkijonoja taulukon avulla kuten harrastusesimerkissä, vaan kysytään aina jäseneltä mikä teksti näytetään mihinkäkin soluun. Samoin lajittelua varten kerrotaan millaisen jonon perusteella lajitellaan. Esimerkin koodi on hieman lyhentynyt kun SailoException
on peritty ajonaikaisesta poikkeuksesta ja näin sitä ei ole pakko ottaa kiinni joka paikassa:
public class SailoException extends RuntimeException {
Esimerkissä voi muokata jäseniä, mutta ei poistaa eikä lisätä. Mikäli muokkausmahdollisuus poistettaisiin, lyhenisi alusta
-metodi melkein puolella (alusta voisi olla myös staattinen).
JasenStringGrid.java
019 public class JasenStringGrid extends Application { 020 @Override 021 public void start(Stage primaryStage) { 022 try { 023 final BorderPane root = new BorderPane(); 024 StringGrid<Jasen> grid = new StringGrid<>(); 025 root.setCenter(grid); 026 027 primaryStage.setScene(new Scene(root)); 028 primaryStage.setTitle("Kerho"); 029 030 Kerho kerho = new Kerho(); 031 kerho.lueTiedostosta("kelmit"); 032 alusta(kerho, kerho.etsi("*", 0),grid); 033 034 primaryStage.setOnCloseRequest((event) -> { 035 try { 036 kerho.tallenna(); 037 } catch (SailoException e) { 038 // TODO viesti 039 } 040 } ); 041 042 primaryStage.show(); 043 } catch(Exception e) { 044 e.printStackTrace(); 045 } 046 } 047 048 049 private void alusta(Kerho kerho, Collection<Jasen> jasenet, StringGrid<Jasen> grid) { 050 Jasen apujasen = new Jasen(); 051 int eka = apujasen.ekaKentta(); 052 int lkm = apujasen.getKenttia(); 053 String[] headings = new String[lkm-eka]; 054 for (int k=eka; k<lkm; k++) headings[k-eka] = apujasen.getKysymys(k); 055 grid.initTable(headings); 056 057 for (int k=eka; k<lkm; k++) grid.setAlignment(k-eka, apujasen.getSijainti(k)); 058 059 grid.setOnCellString( (g, jasen, defValue, r, c) -> jasen.anna(c+eka) ); 060 grid.setOnCellValue( (g, jasen, defValue, r, c) -> jasen.getAvain(c+eka) ); 061 062 grid.setTableMenuButtonVisible(true); // menu, josta voi valita sarakkeet 063 064 grid.setEditable(true); 065 grid.setOnGridLiveEdit((g, jasen, defValue, r, c, edit) -> { 066 String virhe = jasen.aseta(c+eka,defValue); 067 if ( virhe == null ) { 068 try { 069 kerho.korvaaTaiLisaa(jasen); // jotta saadaan muutos 070 } catch (kanta.SailoException e) { 071 // 072 } 073 edit.setStyle(null); 074 Dialogs.setToolTipText(edit,""); 075 } else { 076 edit.setStyle("-fx-background-color: red"); 077 Dialogs.setToolTipText(edit,virhe); 078 } 079 return defValue; 080 }); 081 082 grid.add(jasenet); 083 }
These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.