Az ENSZ 1987-ben július 11-ét a népesedési világnappá (World Population Day) nyilvánította. Bolygónk lakossága aznap érte el az 5 milliárdot. További kerek számok voltak: 1999. október 12-én 6 milliárd, 2011. október 30-án 7 milliárd. További kerek számok várhatóak: 2023 – 8 milliárd, 2037 – 9 milliárd, 2057 – 10 milliárd. A KSH elemzése részletes elemzéseket közöl évről-évre a témában, például: 2019-ben, 2018-ban. A worldometer.info weboldalon folyamatosan frissülő kimutatások érhetők el a népességhez globálisan, valamint országonként is: például Magyarország aktuális népesedési adatai.
A népesedési világnap inspirált egy Java program megtervezésére és megírására. A swing GUI-s program megjeleníti a worldometer.info weboldalról kinyerhető adatok alapján régiónként (kontinensenként) az elérhető adatokat 1950-től 2020-ig az alábbiak szerint egy világtérképen.
Az elkészült program
Tervezés
Objektumorientált szemlélettel, MVC architekturális tervezési mintát követünk, angol nyelvű interfész, osztály, változó, objektum, metódus nevekkel. A projekt neve:
WorldPopulation, a csomag neve:
worldpopulation. Amit lehet, konstansként interfészbe (szeparálva) teszünk és az MVC rétegekhez kötődő osztályok implementálják. A modell minden évszámhoz tárolja a szükséges adatokat, mindezt egyetlen betöltéssel/letöltéssel éri el. A program kliensként hat régióra vonatkozó adatot gyűjt össze, alkalmazkodva a szerver adatforráshoz. A címsorban lévő összesített adat is elérhető közvetlenül a weboldalon, de a kisebb adatforgalom érdekében hasznos inkább a kliensben összesíteni. Mindössze egyetlen eseménykezelés szükséges: a csúszka beállításával megadott évszám alapján frissíteni kell a régiók címkéit és az ablak címsorát. Öröklődés hasznos a feladat megoldása során: egyrészt interfészek, másrészt osztályok között.
Interfészek
Az ősinterfész a
WorldPopulationConstants, benne az évszám intervallum
MIN_YEAR és
MAX_YEAR határaival, valamint a megjeleníthető régiók neveivel tömbben:
REGION_NAME_ARRAY. Két utódinterfész épül az ősre:
ModelConstants és
ViewConstants. Előbbi interfész az adatforráshoz kapcsolódik:
URL_COMMON az URL eleje,
URL_ARRAY az URL végei régiónként tömbben. Utóbbi interfész a megjelenítéshez kapcsolódik:
WORLD_MAP_IMAGE a háttérkép annak
WORLD_MAP_RECT méretével együtt, valamint a régiónkénti
REGION_RECT_ARRAY téglalapok tömbje a kezdeti pozíciókkal/méretekkel,
TITLE a sablon a program címsorához (frissítendő az évszámmal és az összesített népességgel). A megfelelő utódinterfészt mindig implementálja az MVC szerint hozzá illeszkedő osztály.
Osztályok
A belépési pont a
WorldPopulation.java fájlban található.
Három összetartozó elemi adatot fog össze egybe a
RegionData POJO, ezek
name,
year,
population nevű rendre
String,
int,
long típusú adatok. Például: Európa, 2020, 747643253. Tartalmaz két függvényt:
getPopulation(), valamint
toString(). Utóbbi HTML formátumban adja vissza a megjelenítendő adatokat.
A
JLabel-ből származik az igényekhez alakított
RegionLabel osztály. Ennek van előre megadott pozíciója, mérete, betűtípusa, betűmérete, sárga háttérszíne, piros kerete. Ezenkívül a téglalap átlátszó, valamint a benne megjelenő HTML tartalom vízszintesen középre igazított. Némi extra funkció, hogy egérrel megfogva – drag and drop – áthelyezhető, ami a
MouseMotionListener egérmozgást figyelő interfész
mouseDragged() metódusának felülírásával válik lehetővé. A mozgathatóságáért saját maga felel. Példaként közöljük az osztály teljes forráskódját:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
package worldpopulation; import java.awt.Color; import java.awt.Font; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.SwingConstants; public class RegionLabel extends JLabel { public RegionLabel(Rectangle bounds) { setBounds(bounds); setFont(new Font("Tahoma", Font.PLAIN, 14)); setHorizontalAlignment(SwingConstants.CENTER); setBorder(BorderFactory.createLineBorder(Color.RED, 2, true)); setBackground(Color.YELLOW); setOpaque(true); addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseDragged(MouseEvent e) { setLocation(getX()+e.getX()-getWidth()/2, getY()+e.getY()-getHeight()/2); } }); } } |
A webről adatokat szerez és tárolja a
Model osztály, a
java.io és
java.net csomagokra építve. Egy példa: a https://www.worldometers.info/world-population/europe-population/ oldal forrásából nyeri ki az osztály az alábbi adatokat:
|
var dataT=new google.visualization.DataTable( {cols: [ {type:'date',label:'Date'},{type:'number',label:'Europe Population'} ], rows: [ {c:[{v:new Date(1950,6,1)},{v:549328883}]}, {c:[{v:new Date(1951,6,1)},{v:554324469}]}, ... {c:[{v:new Date(2019,6,1)},{v:747182751}]}, {c:[{v:new Date(2020,6,1)},{v:747636026}]} ]}); |
Ezek parszolását követően elkészül egy optimálisnak tekinthető, generikus listákból álló
regionListArray tömb adatszerkezet. A parszolás történhet egyszerű szövegkezeléssel vagy JSON feldolgozással is. Erre épülnek a konstruktorral és vezérlővel összehangoltan működő getter metódusok:
getHTML(),
getRegionList(),
getRegionData(),
getPopulation(). A JSON adatforrás feldolgozását most nem részletezzük, de hasonlóról blogoltunk már: Időjárás Budapesten.
A grafikus felhasználói felületet adja a
JFrame utód
View osztály. Három GUI komponensből áll:
pnWorldMap – háttérkép
JPanel,
lbYear – kiválasztott/aktuális év
JLabel,
slYear – kiválasztható/görgethető aktuális év
JSlider. Izgalmas megoldani egymásra/egymáson elhelyezni a komponenseket. Egy
JLayeredPane komponens
DEFAULT_LAYER rétegére kerül a térképet tartalmazó háttérkép, majd a
PALETTE_LAYER rétegére kerül dinamikusan a hat
RegionLabel osztályú/típusú objektum. A csúszka komponens
slYearStateChanged() eseménykezelő metódusa vezérlőként megszólítja a modell réteget és a visszakapott adatokkal frissíti a nézet réteget (a címsorban lévő összesítéssel együtt, ezres szeparátorokkal).
Ötlet továbbfejlesztésre
Hat különböző weboldal forráskódjából kell összegyűjteni a megjelenítendő adatokat. Ez 2020-ban régiónként 71 számot jelent és hat régió van. Érdemes lehet olyan adattárolást megvalósítani, amely csökkenti a szerverhez fordulások számát, illetve a letöltendő adatok mennyiségét. Hiszen a múltbeli évekhez kötődő historikus adatok nem változnak. Ha ezekre valamilyen formában a program emlékszik, akkor elegendő az utolsó tárolt évből kiindulva az aktuális évig évenként, régiónként lekérni mindössze 6, 12, 18… számot, a program utolsó futtatásának évéből kiindulva. Ez lényegesen kevesebb lenne, mint a jelenlegi 6*71 lekért szám. A koncepció kulcsszava: inkrementális adatfrissítés. Ha megvalósítjuk az ötletet, akkor figyelni kell arra, hogy az aktuális/utolsó évben az adatok akár másodpercenként is változhatnak.
A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.
A feladat a Java SE szoftverfejlesztő tanfolyam tematikájához kötődik (ha a swing GUI-ra koncentrálunk és az adatok helyi fájlrendszerből elérhetők), és a Java EE szoftverfejlesztő tanfolyam tematikájához kapcsolódik (ha az adatokat közvetlenül a webről olvassuk).