Tkinter Canvas grafikák elmentése és fájlból történő megjelenítése

A tkinter modul vászon (Canvas) grafikus elemén a különféle típusú rajzelemekkel (ellipszis, ellipszisív, sokszög, téglalap, vonal) akár meglehetősen összetett grafikákat is tudunk alkotni. A rajzelemek létrehozása általában a vászonelemre meghívott konstruktormetódusokkal történik. De lehetséges az is, hogy egy rajzszerkesztő programot készítünk és/vagy használunk, ahol a rajzelemeket a program által biztosított módon helyezzük a vászonra és vizuálisan rendezzük el egér- vagy billentyűműveletekkel.

A kérdés az, hogy hogyan őrizhetnénk meg az alkotásunk eredményét egy fájlban úgy, hogy később a fájlból a grafika megjeleníthető legyen? És mindezt lehetőleg úgy, hogy nem támaszkodunk a szabványos könyvtáron túlmutató külső csomagokra vagy alkalmazásokra.

Nyilván egy lehetséges út a képernyőképmentés (printscreen). Ez azonban rasztergrafikát eredményez, aminek meg vannak a maga hátrányos jellemzői, pl. rögzített felbontás, nagyításnál minőségromlás, és formátumtól és képmérettől függő képfájlméret. Ráadásul a tkinter PhotoImage objektumot csak meglehetősen korlátozott számú képformátum esetén tudjuk használni.

E helyett, mivel a megjelenített grafikához a vásznon rendelkezésre állnak a rajzelemek, vektorgrafikusan fogjuk leírni a képet. Ennek elvét olvashatjuk ezen az ábrán:

Az elvet programban a következőképpen valósítjuk meg.

Az egyes rajzelemek adatait egy szótárban gyűjtjük össze, amelyben a kulcsok a rajzelemek egyedi azonosítói, a kulcsokhoz tartozó értékek pedig sorozat típusú konténerek, amelyek elemei a rajzelem típusa, a koordináták sorozata, valamint egy, a konfigurációs paraméternév-érték párokat tartalmazó szótár.

Ezen adatok mindegyike egyszerűen kinyerhető a vászon elemre meghívott megfelelő metódussal. A típust a type(), a koordinátákat a coords(), a konfigurációt tartalmazó szótárt a itemconfig() metódus hívásával kaphatjuk meg.

A rajzelemek adatait tartalmazó szótárt fájlba mentjük, mégpedig JSON formátumban, mert így a mentést és majd a visszaolvasást egyszerűen el tudjuk végezni.

Ahhoz, hogy tudjuk, hogy a fájl mit tartalmaz, legyen a fájl kiterjesztése .tcg, ami a tkinter canvas grafika kezdőbetűiből lett képezve.

A canvas grafikák ilyen fájlokba történő mentését teszi lehetővé az alább látható TcgFileMaker osztály.

A TcgFileMaker példánya egy .tcg kiterjesztésű, tkinter canvas grafikát leíró fájlt készít a generate_tcg_file_from_factory() vagy a generate_tcg_file_from_canvas() metódusok meghívásával. Az előbbit akkor kell használni, ha a grafika egy grafika-előállító függvényben van definiálva. Az utóbbi metódust pedig akkor, ha a grafika egy vászon elemen van létrehozva és megjelenítve.

A grafika-előállító függvény egy olyan függvény, amely egyetlen, kötelezően megadandó pozícionális argumentumot fogad, mégpedig egy vászon elemet, amelyen a grafika az összetevő rajzelemek (téglalap, sokszög, ellipszis, ellipszisív és vonal) létrehozásával és megfelelő konfigurációjával valósul meg a függvény törzsében szereplő utasításokkal. Ilyen grafika-előállító függvényekre láthatunk alább példát.

Ezekhez nem fűzünk kommentet, mert most nem ezek kialakításának magyarázata a cél; a kívánt grafika rajzelemekből való felépítésének fejben vagy papíron való megtervezését követően a megvalósításhoz csak középszintű koordinátageometriai ismeretekre van szükség. Azt viszont megfigyelhetjük, hogy ha átlátszóság érzetét akarjuk kelteni, vagyis a grafika adott rajzelemének kitöltő színe a háttérszínnel egyezzen meg, akkor egyrészt a fill konfigurációs paraméterhez a vászon aktuális kitöltőszínét kell rendelni, másrészt, ahhoz hogy később a fájlba mentésnél a transzparenciára vonatkozó információ is rögzüljön, az adott rajzelemhez a „fill_transparent” tag-et kell társítani. Hasonlóan kell eljárni, ha a rajzelem körvonalát az aktuális háttérszínnel egyezőnek akarjuk, csak ilyenkor a rajzelemhez az „outline_transparent” tag-et kell adni.

A TcgFileMaker példányosításakor létrejön egy Canvas példány, amelynek szülőelemét a konstruktorban kell megadni. Ez legtöbbször a gyökérelem (főablak), de lehet más is, például egy keret (Frame) elem.

Ha a TcgFileMaker példánnyal létrehoztunk egy vagy több .tcg fájlt, akkor a következő kérdés, hogy hogyan tudjuk ezeket használni a GUI programunkban. Erre szolgál a Tcg osztály, amelynek definíciója ez:

A Tcg osztály példánya az inicializáláskor megadott fájl által definiált tkinter canvas grafikát állítja elő és jeleníti meg az inicializáláskor megadott vászon elemen, amikor a render() metódus meghívásra kerül. Ezt követően a grafika áthelyezhető és átméretezhető a példányon meghívott megfelelő metódusokkal. E metódusok használata helyett a Canvas saját metódusaival is megvalósíthatók a műveletek, amelyekhez a Tcg példány id_tag azonosító tag-e használható az adott Canvas metódus által elvárt rajzelem-azonosítóként.

Ha a render() metódus hívásakor, vagyis ha a grafika előállításakor egy rajzelemen a „fill_transparent” tag található, akkor az adott rajzelem kitöltőszíne a vászon aktuális háttérszínével fog megegyezni, az átlátszóság érzetét keltve. Ha a grafika előállításakor a rajzelemen az „outline_transparent” tag található, akkor az adott rajzelem körvonalának színe a vászon aktuális háttérszínével fog megegyezni. Ebből következik, hogy a megjelenített grafika traszparens részei csak akkor hatnak átlátszónak, ha alattuk csak a vászon elem van. Ha a megjelenítési sorrendben más grafika van alattuk, akkor nem érvényesül az átlátszóság. Ez kompromisszum a grafika előállításának (a grafika-előállító függvények kódolásának) egyszerűsége és a teljes, valódi átlátszóság között. Ez utóbbi ugyanis megvalósítható, de ekkor a grafikát sokkal bonyolultabb geometriával, sok csúcsponttal rendelkező sokszögekből kell felépíteni.

Arra is lehet igény, hogy mielőtt egy .tcg fájlt használnánk, megtekintsük, hogy milyen grafikát képvisel. Erre szolgál a következőkben mutatott view_tcg() és view_tcg_files() függvény. Az előbbi egyetlen .tcg fájl által definiált grafikát jelenít meg egy ablakban. Az utóbbi több .tcg fájl által definiált grafikákat egy közös ablakban táblázatos elrendezésben jeleníti meg. Ezek a függvények már a Tcg osztályt használják, így egyúttal a Tcg osztály alkalmazási példájaként is tekinthetünk rájuk.

A TcgFileMaker és Tcg osztályok, valamint a view_tcg() és view_tcg_files() függvények alkotják a tkinter canvas grafikák fájlba mentésének és onnan történő megjelenítésének és használatának eszköztárát. Ezért szerepelnek ezek egy közös, tcg nevű modulban. Ha egy GUI programban a grafikákat menteni akarjuk, és/vagy már .tcg fájlokba elmentett grafikákat akarunk behívni és azokkal dolgozni, akkor a tcg modult kell beimportálni, és használni a benne foglalt osztály- és függvényobjektumokat.

A tcg modul objektumai használatának szemléltetéséhez két GUI alkalmazást mutatunk.

Tcg fájlokat létrehozó alkalmazás

Az alkalmazást megvalósító TcgFileCreatorApp osztály a tcg_file_creations nevű modulban van definiálva. A modult szkriptként futtatva egy oly GUI alkalmazást indít el, amely egy megadható modulfájlban definiált egy vagy több tkinter canvas grafikát előállító függvény alapján a grafikákat leíró .tcg kiterjesztésű fájlokat készít és ment el egy előre megadható mappába. E mappába elmentett létező .tcg fájlok által definiált grafikákat egy közös ablakban táblázatos elrendezésben is meg lehet jeleníteni.

A működéshez a grafika-előállító függvényekre vonatkozóan vannak követelmények, amelyek az alábbiak:

  • nevük create_ kezdetű,
  • csak egyetlen kötelezően megadandó pozícionális argumentumot fogadhatnak, ami a Canvas példány,
  • az átlátszóvá tenni kívánt rajzelemhez a „fill_transparent” tag van rendelve,
  • az aktuális canvas háttérszínnel egyező körvonal szín eléréséhez a rajzelemhez az „outline_transparent” tag van rendelve.

Az alkalmazás indítása után beviteli mezőkből és vezérlő gombokból álló felhasználó felület jelenik meg.

A grafika-előállító függvényeket tartalmazó modulfájl elérési útvonalát és az elkészült .tcg kiterjesztésű fájlok mentési mappájának útvonalát a megfelelő beviteli mezőkben két módon adhatjuk meg. Vagy manuálisan begépelve, vagy a beviteli mezők jobb szélén található, három ponttal jelzett nyomógomb megnyomására felugró párbeszédablak segítségével.

Ha ezeket megadtuk, akkor a „TCG fájlnevek generálása” gombot megnyomva a modulfáljban található grafika-előállító függvények nevei alapján a listadobozban egymás alatt fájlnevek jelennek meg, amely neveken a grafikák .tcg kiterjesztésű fájlokba menthetők. Ezek a nevek azonban csak ajánlott, alapértelmezett nevek. Ha mást szeretnénk, akkor módosítani lehet úgy, hogy kétszer a névre kell kattintani a bal egérgombbal, és a felugró beviteli párbeszédablakba az új nevet kell beírni, majd az OK gomb lenyomásával érvényesíteni.

A „Grafika leíró fájlok készítése” gomb lenyomására a .tcg kiterjesztésű fájlok elkészülnek és a korábban megadott mappába mentődnek. A sikeres műveletekről egy üzenetablak tájékoztat. Ha a fájlok készítése valamiért nem sikerül, akkor a hiba valószínű okáról szintén egy üzenetablakban kapunk információt. A megadott mentési mappában található .tcg fájlok által leírt grafikákat egyetlen ablakban táblázatos elrendezésben tekinthetjük meg, ha a „Mentett grafikák megjelenítése” gombot megnyomjuk.

Az alkalmazás grafikus felhasználói felületét és egy eredményképet mutat az alábbi ábra, ahol a használat lépéseit sorszámokkal jeleztük a megfelelő nyomógombokon. Itt az is látható, hogy akár több modulban szereplő grafika-előállító függvényekkel is dolgozhatunk.

Montázskészítő alkalmazás

Ezt az alkalmazást a TcgMontageMakerApp osztály képviseli, amely a tcg_montage_maker modulban definiált. E modult szkriptként futtatva egy olyan GUI alkalmazás indul el, amellyel .tcg fájlokban definiált grafikák felhasználásával egy új grafikát lehet készíteni az alkalmazás erre szolgáló felületén. Az egyéni terv szerint elrendezett (áthelyezett és/vagy átméretezett) komponens grafikákból álló montázst egy megadható mappába lehet elmenteni .tcg fájl formátumban. Ezt követően a montázst meg is lehet jeleníteni egy külön ablakban. Az alkalmazás indítása után a beviteli mezők és vezérlő gombok a bal oldalon, a vizuális grafikai tervező felület a jobb oldalon látható.

A tcg_montage_maker modul tartalma a következő:

Az alkalmazás grafikus felhasználói felületét és példa eredményképeket a következő ábrák mutatják. Itt szintén feltüntettük a használati lépések sorszámait a megfelelő nyomógombokon.

Ez az alkalmazás – minthogy alapvetően demonstrációs célú – nem rendelkezik egy képszerkesztő teljes funkcionalitásával. De persze egyéni igényeknek megfelelően továbbfejleszthető: pl. beviteli mezők és nyomógombok helyett menürendszer, és funkcionalitásban kiegészíthető a tükrözés és forgatás geometriai transzformációkkal. Ez utóbbi alkalmazásához azonban alaktartóan forgatható rajzelemekből felépített grafikák szükségesek. Ehhez lásd a „Forgatható ellipszis, ellipszisív és téglalap” című korábbi bejegyzést. Ha pedig az alkotásunk rajzelemekből való felépítését mások elől el akarjuk rejteni, akkor .tcg fájlokat akár titkosítani is lehet.

A fenti forráskódokat a https://github.com/pythontudasepites/saved_canvas_graphics linken is el lehet érni. Itt az alkalmazások használatának leírása szintén megtalálható.

A tkinter canvas grafikák megtervezése és .tcg fájlok készítése igényel némi időt, de ha olyan képekre, grafikákra van szükség, amelyek a Canvas rajzelemeiből viszonylag egyszerűen létrehozhatók, akkor érdemes megtenni, mert akkor a vektorgrafika előnyeit élvezhetjük, és a mások által készített képek liszensz kérdése sem merül fel.

E bejegyzés témájához a Python tudásépítés lépésről lépésre című e-könyv számos fejezete kapcsolódik. Elsősorban a „Grafikus felhasználói felület készítése”, a „Panelprogram-modulok” és a „Mentsük, ami menthető! – fájlok és mappák” fejezetek. A „Készétel fogyasztás – a szabványos könyvtár moduljainak használata” fejezetből pedig a „Dinamikus modulimportálás” alfejezetet is érdemes még átfutni.

É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.