Tartalomjegyzék

< wxPython GUI

Glade MVC

Külön osztályba rendezés

Végezzük el a következő beállításokat:

Ezek után, ha kódot generálunk, külön állományokba fog minden osztályt kerülni, aminek a nevét átírtunk.

A program indítása

A program mindig a wx.App osztályból származtatott objektummal indul. Alapesetben, ez egy app.py nevű fájlban található.

MVC esetén a wxGalde segítségével a nézetfájlokat egy views könyvtárba szokás generálni. Viszont itt fog létrejönni az app.py állomány is, ami probléma a controllers models és views könyvtárak elérése miatt. Az app.py fájlt a views könyvtárral egy szintre kell tenni. Ilyen esetben az app.py állomány létrehozását magunknak kell megoldani.

Ehhez a következőket tegyük:

projekt01/
  `-src/
     |-controllers/
     |-models/
     |-views/
     `-app.py   

Az app.py fájlból hívjuk a controllers könyvtárban található MainController-t. A MainController-ben példányosítjuk a models könyvtárban található MainModel osztályt, a views könyvtárban található MainFrame osztályt.

Mivel az alkalmazás az src könyvtárból indul, ezért a controllers könyvtárban található kontrollerosztályokban látszanak a többi könyvtárak osztályai.

A program.wxg fájl helye

A .wxg fájl lehet a controllers, models és views könyvtárak mellet, de elhelyezhetjük a views könyvtárban is tetszés szerint.

projekt01/
  `-src/
     |-controllers/
     |-models/
     |-views/
     `-projekt01.wxg
projekt01/
  `-src/
     |-controllers/
     |-models/
     `-views/
         `-projekt01.wxg

Általános példa

UML diagram

Könyvtárszerkezet

projekt01/
 `-src/
    |-controllers/
    |   `-main_controller.py
    |-models/
    |  `-main_model.py
    |-views/
    |  `-MainFrame.py
    |  `-projekt01.wxg
    `-projekt01.py

A views könyvtár állományait a wxGlade programmal készítjük, amíg a többit tetszőleges kódszerkesztővel.

A wxGalde használata során megkötés, hogy nem lehet különböző neve az osztálynak és a fájlnak. Ezért MainFrame.py nevű fájlt hozunk létre, MainFrame osztállyal.

Kód

projekt01.py
import wx
from controllers.main_controller import MainController
 
class Projekt01App(wx.App):
    def OnInit(self):
        MainController()
        return True
 
app = Projekt01App(False)
app.MainLoop()
controllers/main_controller.py
import wx
 
from views.MainFrame import MainFrame
from models.main_model import MainModel
 
class MainController:
    def __init__(self):
        main_frame = MainFrame(None, wx.ID_ANY, "")
        main_frame.Show()
models/main_model.py
class MainModel:
    def get_name():
        return 'János'
views/MainFrame.py
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 1.0.0a9 on Sat Nov 28 23:23:19 2020
#
 
import wx
# begin wxGlade: dependencies
# end wxGlade
 
# begin wxGlade: extracode
# end wxGlade
 
 
class MainFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MainFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.SetTitle("frame")
 
        self.panel_1 = wx.Panel(self, wx.ID_ANY)
 
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
 
        self.button_1 = wx.Button(self.panel_1, wx.ID_ANY, "button_1")
        sizer_1.Add(self.button_1, 0, wx.ALL, 5)
 
        self.panel_1.SetSizer(sizer_1)
 
        self.Layout()
        # end wxGlade
 
# end of class MainFrame
views/projekt01.wxg
<?xml version="1.0"?>
<!-- generated by wxGlade 1.0.0a9 on Sat Nov 28 23:23:14 2020 -->
 
<application encoding="UTF-8" for_version="3.0" header_extension=".h" indent_amount="4" indent_symbol="space" is_template="0" language="python" mark_blocks="1" option="1" overwrite="1" path="./src" source_extension=".cpp" top_window="frame" use_gettext="0" use_new_namespace="1">
    <object class="views.MainFrame" name="frame" base="EditFrame" instance_class="MainFrame">
        <size>400, 300</size>
        <title>frame</title>
        <style>wxDEFAULT_FRAME_STYLE</style>
        <object class="wxPanel" name="panel_1" base="EditPanel">
            <object class="wxBoxSizer" name="sizer_1" base="EditBoxSizer">
                <orient>wxVERTICAL</orient>
                <object class="sizeritem">
                    <option>0</option>
                    <border>5</border>
                    <flag>wxALL</flag>
                    <object class="wxButton" name="button_1" base="EditButton">
                        <label>button_1</label>
                    </object>
                </object>
            </object>
        </object>
    </object>
</application>

Minta

MVC wx.App osztállyal

Ebben a példában, meghagytuk az App osztály generálást. Így az app osztály példánya nem egy kontrollert hív, hanem előbb MainFrame osztályt.

Az osztály nevét így adjuk meg:

views.LeftPanel

A nevet a views. szóval vezettük be. A views egy könyvtár lesz, amit a wxGlade automatikusan létrehoz.

Az alkalmazásosztályt ne tegyük a views könyvtárba, mert felesleges, annak helye az src könyvtár marad.

Az Output path src legyen. Nem szükséges elé pont és per, vagy utána / karakter.

Így következő szerkezetet kapjuk:

tarol/
  |--src/
      |--views/
      |   |--LeftPanel.py
      |   `--MainFrame.py
      `--app.py

Így elkészíthetjük az src könyvtárban a controllers és models könyvtárakat.

Kontroller és modell hozzáadása

tarol/
 `--src/
     |--controllers/
     |   `--LeftController.py
     |--models/
     |   `--LeftModel.py
     |--views/
     |   |--LeftPanel.py
     |   `--MainFrame.py
     `--app.py

Eseménykezelés

Az eseménykezelést, most ne bízzuk a wxGlade-re, azt mi fogjuk megvalósítani a LeftController.py állományban.

Forrás

Az app.py fájlhoz nem nyúlunk. Ezt minden esetben újragenerálja a wxGlade.

src/tarol.py
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 0.9.6 on Tue Aug 11 01:18:08 2020
#
 
# This is an automatically generated file.
# Manual changes will be overwritten without warning!
 
import wx
from views.MainFrame import MainFrame
 
 
class TarolApp(wx.App):
    def OnInit(self):
        self.frame = MainFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True
 
# end of class TarolApp
 
if __name__ == "__main__":
    tarol = TarolApp(0)
    tarol.MainLoop()

Írjunk egy LeftModel osztályt, amelnyek van egy szoveg adattagja, és egy setValue() metódusa:

src/models/LeftModel.py
class LeftModel:
    def __init__(self):
        self.szoveg = None
    def setValue(self, szoveg):
        self.szoveg = szoveg
        print("Model ok")

Írjunk egy LeftController osztályt:

src/controller/LeftController.py
import wx
from views.LeftPanel import LeftPanel
from models.LeftModel import LeftModel
 
class LeftController:
    def __init__(self, panel: LeftPanel):
        self.panel = panel
        self.panel.Bind(wx.EVT_BUTTON, self.onClickGoButton, self.panel.goButton)
        self.leftModel = LeftModel()
 
    def onClickGoButton(self, event):
        valtozo = self.panel.text1.GetValue()
        self.leftModel.setValue(valtozo)  

Legyen egy Panel:

src/views/LeftPanel.py
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 0.9.6 on Tue Aug 11 01:26:08 2020
#
 
import wx
# begin wxGlade: dependencies
# end wxGlade
 
# begin wxGlade: extracode
# end wxGlade
 
 
class LeftPanel(wx.Panel):
    def __init__(self, *args, **kwds):
        # begin wxGlade: LeftPanel.__init__
        kwds["style"] = kwds.get("style", 0)
        wx.Panel.__init__(self, *args, **kwds)
        self.text1 = wx.TextCtrl(self, wx.ID_ANY, "")
        self.goButton = wx.Button(self, wx.ID_ANY, "Mehet")
 
        self.__set_properties()
        self.__do_layout()
        # end wxGlade
 
    def __set_properties(self):
        # begin wxGlade: LeftPanel.__set_properties
        pass
        # end wxGlade
 
    def __do_layout(self):
        # begin wxGlade: LeftPanel.__do_layout
        sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, u"Tevékenységek"), wx.VERTICAL)
        sizer_2.Add(self.text1, 0, wx.ALL | wx.EXPAND, 6)
        sizer_2.Add(self.goButton, 0, wx.ALL | wx.EXPAND, 6)
        self.SetSizer(sizer_2)
        sizer_2.Fit(self)
        self.Layout()
        # end wxGlade
 
# end of class LeftPanel

Hívjuk meg a MainFrame osztályban a LeftController-t.

src/views/MainFrame.py
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 0.9.6 on Mon Aug 10 18:01:18 2020
#
 
import wx
from controllers.LeftController import LeftController
 
# begin wxGlade: dependencies
from views.LeftPanel import LeftPanel
# end wxGlade
 
# begin wxGlade: extracode
# end wxGlade
 
 
class MainFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MainFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((400, 300))
        self.leftPanel = LeftPanel(self, wx.ID_ANY)
 
        self.__set_properties()
        self.__do_layout()
        # end wxGlade
 
        LeftController(self.leftPanel)
 
    def __set_properties(self):
        # begin wxGlade: MainFrame.__set_properties
        self.SetTitle("frame")
        # end wxGlade
 
    def __do_layout(self):
        # begin wxGlade: MainFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(self.leftPanel, 1, wx.ALL | wx.EXPAND, 6)
        self.SetSizer(sizer_1)
        self.Layout()
        # end wxGlade
 
# end of class MainFrame