MVC programfelépítés megfigyelő minta használatával GUI alkalmazásban

Az előző bejegyzésben az MVC szerkezetre épülő, nem grafikus felhasználói felületű alkalmazásra adtunk egy szemléltető példát, ahol a megfigyelő programtervezési mintát (observer design pattern) alkalmaztuk a megjelenítést végző objektumok értesítésére, hogy a modell állapota megváltozott, és ennek megfelelően módosuljon a megjelenítés.

Mindazonáltal az MVC architektúra leginkább a grafikus felhasználói felületet (GUI) kínáló alkalmazásokban használatos, ezért most az előző bejegyzésben szereplő modellhez (gépjármű gyorsítása, lassítása) elkészítjük a GUI-t.

Ahogy arról előzőleg szó volt, az MVC struktúra előnye, hogy a felhasználói felületet anélkül tudjuk változtatni, hogy a modellt képviselő kódot módosítani kellene. Ez a helyzet a példánk esetében is, vagyis a modell kódja nem változik, amit itt mutatunk:

A programunkban az MVC egyes összetevőit külön modulokba szerveztük, ami az áttekinthetőséget javítja. Ennek megfelelően a Car, Publisher és Subscriber osztályokat tartalmazó modell a model.py modulfájlba kerül.

A Car példány aktuális sebességét az előző bejegyzésben foglaltakhoz hasonlóan két módon jelenítjük meg: vizuálisan és szövegesen. Az erre szolgáló két osztály nevén sem változtatunk, vagyis a két View osztály a CarSpeedView1 és CarSpeedView2 lesz most is. Az implementációjuk természetesen eltér az előzőkétől, viszont az nem változik, hogy mindketten megfigyelő objektumok lesznek, ezért a Subscriber osztályt öröklik. Ami a grafikus megvalósítást illeti, alapból mindketten a tkinter modul Frame objektumai lesznek, ezért a Frame osztályt is öröklik. Mivel Pythonban lehetőség van a többszörös öröklésre (multiple inheritance), így a CarSpeedView1 és CarSpeedView2 mind a Frame, mind a Subscriber osztályokat örökölheti problémamentesen, hiszen ez utóbbi két osztálynak nincs azonos metódusa.

A CarSpeedView1 a sebességérték vizuális megjelenítését egy értékskálán mutatja, amit a tkinter Scale grafikus objektumával valósítunk meg. A CarSpeedView2 a sebességre vonatkozó szöveges tájékoztatást egy címke (Label) grafikus elemen jeleníti meg. Itt nem csak az aktuális sebességről kapunk információt, hanem egy figyelmeztető szöveg is ki lesz írva akkor, ha az aktuális pillanatnyi sebesség a megadott sebességkorlátot túllépi.

Mindkét osztályt a view_gui.py modulban definiáljuk, amelyek definícióit alább láthatjuk:

Ugyanebben a modulban definiáljuk azon objektum osztályát (DataInputGUI), amely az autó gyorsításának/lassításának értékét a felhasználótól fogadni képes, és egy felhasználói eseményre, amely jelen esetben egy gombnyomás, kezdeményezi (a Controller-en keresztül) a modell állapotának (autó sebessége) módosítását a beviteli mező aktuális értéke alapján.

Az eddig említett osztályok (DataInputGUI, CarSpeedView1 és CarSpeedView2) felelősek tehát a felhasználói adatbevitel lekezeléséért, valamint a modell aktuális állapotának eltérő megjelenítésért. Ahhoz, hogy ezek működjenek, egy főablakot megjelenítő osztály részeivé kell tenni. Ezt a MainWindow nevű osztályt szintén a view_gui.py modulban definiáljuk. A DataInputGUI és MainWindow osztályokat a következő programkód mutatja:

Végül nem maradt más hátra, mint a Controller osztály definiálása. Ez lényegében abból áll, hogy eltárolja a modell objektum (Car példány) referenciáját és a View objektumokat (CarSpeedView1, CarSpeedView2) felveszi a modell értesítési listájára. Egyetlen metódusával a modell állapotváltozását lehet kezdeményezni, a sebességváltozás értékének megadásával. A main_controller.py modulba kerülő Controller osztály látható alább. E modul egyben a fő modul is, ami a létrehozza a MainWindow és Controller objektumokat és elindítja az alkalmazást:

A következő ábrán a megjelenő kezdőablak látható, valamint azon fázisok képei, amikor a gyorsítást kezdeményező gombot nyomogatjuk, vagy nyomva tartjuk. Példát láthatunk arra, amikor túllépjük a sebességlimitet, amit utána lassítással hozunk vissza a megengedett tartományba.

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 következő részei kapcsolódnak: az „Osztály vigyázz! – típuslétrehozás osztályokkal” fejezet, a „Készétel fogyasztás a szabványos könyvtár moduljainak használata” fejezet „Absztrakt osztályok” alfejezet, az „Öröklődés” fejezeten belül a „Öröklés több szülőtől” alfejezet, a „Grafikus felhasználói felület készítése” fejezet.

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