Hogyan készítsünk KRESZ táblákat rajzoló programot? – 1.rész

Ebben a bejegyzésben olyan program kidolgozását kezdjük el, amellyel közlekedési jelzőtáblákat – konkrétabban tiltó táblákat – jeleníthetünk meg grafikus felhasználói felületen. Azért választottuk e KRESZ táblákat, mert elég változatosak, viszont van közös vonásuk, hogy mindegyik kör alakú egy piros szegéllyel. Az egyes táblák a tábla közepén levő tartalomban térnek el, amely lehet szám, szöveg (pl. sebességkorlátozó táblák) vagy piktogram (pl. előzni tilos).

Így e táblák nem csak arra adnak lehetőséget, hogy megnézzük miként kell elindulni egy összetettebb rajzelem elkészítésénél, hanem egyéb implementációs kérdések felvetésére és megoldások bemutatására is alkalmas. Például arra, hogy a kör alakú piros szegéllyel rendelkező, belül üres „Mindkét oldalról behajtani tilos” tábla programbeli modellje nem csak önállóan használható, hanem a többi táblát is származtatni lehet belőle, mert csak a belső részt kell tartalommal kitölteni. Más szóval, ha ezt a táblát egy osztályban valósítjuk meg, akkor a többi tiltó tábla ennek specializált utódosztályaiként állítható elő például attól függően, hogy szöveg (szám) vagy piktogram szerepel a tábla közepén.

Azt is megnézzük majd, hogy hogyan rendeljünk eseményeket e táblákhoz, amelyeket például arra használhatunk, hogy növeljük vagy csökkentsük a táblák méretét. Ez utóbbi feladat, ahogy majd látni fogjuk, nem is annyira magától értetődő, szükség lesz a megvalósításhoz némi gondolkodásra.

Most ebben a bejegyzésben egyelőre csak az alapot jelentő „Mindkét oldalról behajtani tilos” táblát valósítjuk meg.

Ha Pythonban a tkinter modult használjuk a GUI felület fejlesztéséhez, akkor a rajzolást a vászon grafikus vezérlőelemen (Canvas widget) tudjuk megtenni. Mivel egy összetett rajzot kívánunk készíteni, és ezt több példányban használni, ezért egy osztályt definiálunk, amely a Canvas osztályt örökli. Az osztály neve legyen ProhibitorySign. Az osztálydefiníciót alább láthatjuk.

Mivel a tiltó táblák kör alakúak, ezért a vászon négyzet lehet. Ennek megfelelően a ProhibitorySign osztály __init__ metódusában egyetlen méretadatot kérünk csak be. A másik paraméter (master) a szülőelemet /pl. gyökérablak (root)/ fogadja.

Bár nem lenne feltétlenük szükséges, de most biztosítjuk azt a rugalmasságot, hogy ha nem adunk meg oldalméret adatot, akkor a master méretéhez igazodik majd a vászonpéldány, amit most az osztályban a self reprezentál.

A következő lépés két eltérő sugarú koncentrikus kör rajzolása a vásznon. A külső kört piros színnel töltjük majd ki. A kisebb belső kör pedig fehér lesz. Így alakul ki majd a piros szegély.

A körök létrehozásához először meghatározzuk a körök közös középpontját, amely x, y koordinátái a négyzetalakú vászon aktuális oldalméretének felével egyeznek meg.

A következő körjellemző a sugár. A külső, azaz a nagyobb sugarú kör átmérője megegyezik a vászon oldalméretével, ezért a külső kör sugara ennek fele. A belső kör sugara kisebb kell, hogy legyen, hogy a piros szegély látszódjon. Elvileg szabadon megválaszthatjuk a külső kör sugarához viszonyítva, de azon tartományon belül kell maradni, ami olyan széles szegélyt eredményez vizuálisan, amit a KRESZ tiltó tábláin látunk. Megfelelőnek tűnik, ha a belső kör sugarát a külső 80%-ára állítjuk be.

Most már következhet a körök kirajzolása. Ezt a vászonpéldányra meghívott create_oval() metódussal tehetjük meg, amelynek első argumentumpárja a kör befoglaló négyzetének balfelső pontjának, a második argumentumpár pedig a jobb alsó pontjának x és y koordinátái kell, hogy legyenek. Ezeket kell előbb előállítani a középpont és sugár ismeretében. Ez elég egyszerű, hiszen a balfelső pont koordinátáit úgy kapjuk meg, hogy a középpont koordinátáiból levonjuk a sugár értékét, a jobb alsó ponthoz pedig a középpont koordinátáihoz hozzáadjuk a sugár értékét. A szegély piros színének kialakításához a külső kör létrehozásakor a fill paraméternek a „red” értéket adjuk, a belső kör esetében ugyanezen paraméter a fehér színt jelölő „white” karakterláncot kapja.

Ezzel lényegében kész az osztálydefiníció. A megadott tesztkódsorokkal ki is próbáljuk az alkotásunkat.

Először létrehozzuk a gyökérablakot (root), és azt egy megadott méretre állítjuk be. Ezt követően létrehozzuk a ProhibitorySign egy példányát a root és oldalméret megadásával. Utána – mivel e példány egyben egy vászon grafikus elem is – lehelyezzük a gyökérablakban a pack() metódussal. Majd pedig belépünk az eseményfigyelő állapotba.

Az eredményt a képen láthatjuk:

Az osztálydefiníció __init__ metódusának végén szerepel még egy metódushívás, ami az alatta definiált metódust hívja meg. A neve alapján nem nehéz kitalálni a célját. Ebben fogjuk definiálni azokat az egér és billentyűzet eseményeket, amelyekre szeretnénk, hogy a táblánk valamilyen módon reagálna.

Ezzel folytatjuk a következő bejegyzésben.

E bejegyzés tartalmához a Python tudásépítés lépésről lépésre című e-könyv „Grafikus felhasználói felület készítése” fejezetének alábbi alfejezeteiben találunk bővebb kifejtést: „Grafikus elemek konfigurálásának módjai”, „A grafikus elemek fajtái, létrehozásuk és konfigurálásuk” alfejezet „Vászon” alcím, továbbá az „Osztály vigyázz! – típuslétrehozás osztályokkal”, és „Öröklődés” fejezetek.

Érdekel a Python tudásépítés lépésről lépésre az alapoktól az első asztali alkalmazásig című e-könyv.