Hlavní navigace

Modelování: Ukázka

18. 8. 2014 19:48 (aktualizováno) | Petr Blahoš

V minulém díle jsme si udělali hierarchii a přidali malý nástroj na mapování události na obslužnou funkci. Dnes si to můžeme dát všechno dohromady, ať konečně vidíme, o co mi celou tu dobu jde. Opět tedy github/modellerkit, tentokrát step06. Zase k tomu budeme potřebovat wxPython.

Tak rovnou do toho. Spusťte si view01.py. To hlavní, čeho jsem chtěl dosáhnout najdeme navěšené na tlačítka:

    def on_next(self, evt):
        " Zobrazí nahodný produkt. "
        self.model.set_product("AAAQA%s" % random.randint(0, 9), 1)

    def on_add_op(self, evt):
        " Přidá náhodnou operaci. "
        proc_op = random.choice(self.model.process)
        self.model.operations.append(production.ProductOperation(
            operation=proc_op.operation,
            tm=datetime.datetime.now(),
            workplace=100,
        ))
        # normální přidání do listu


    def on_del_op(self, evt):
        " Smaže vybranou operaci. "
        sel = self.ops_view.GetFirstSelected()
        if -1 != sel:

            del self.model.operations[sel]
            # normální mazání v listu

A ještě model.set_product dělá tohle:

    def set_product(self, article, sn):
        " Nastaví aktuální výrobek. "

        self.article = article

        self.sn = sn

        self.process = self.server.get_process(article, sn)

        self.operations = self.server.get_product_ops(article, sn)
        # normální přiřazení hodnot do proměnných

To je všechno. Nikde se tam neříká: Zaktualizuj mi tabulku a počet ks.pod tabulkou!, ani Zaktualizuj mi view!, prostě nic. Taky máme jistotu, že nikdo nemůže udělat:

model.article = 123
model.sn = "AHOJ"
model.process[3] = (1, 2, 3)
model.process[3].operation = 30

Teď to view

Tak tedy, do view si normálně naházíme ty prvky, ve kterých chceme něco zobrazovat, t.j. wx.StaticText pro výrobek a počítadla, a MVCList (k němu se ještě dostaneme) pro ty dvě tabulky. Dál si uděláme Mapper a pověsíme ho na model. Po kouskách:

        self.mapper = hotmodel.Mapper()
        self.mapper.add_route("/process", "", self.proc_view.handle_reset,)
        self.mapper.add_route("/operations", "", self.ops_view.handle_reset,)

Tady jsme pověsili všechny operace nad těmi listy na reset. Funguje to, ale pro každou událost celou tabulku smažeme a naplníme znovu. Je to tupé, ale teď chci krátký kód.

        self.mapper.add_route(
            "/process",
            "",
            lambda m, fqn, event, key: self.update_count(m, self.proc_count),
        )
        self.mapper.add_route(
            "/operations",
            "",
            lambda m, fqn, event, key: self.update_count(m, self.ops_count),
        )

Tímto řešíme počítadla pod tabulkami – zase všechny události, ale tady to už tak tupé není, protože všechno, kromě update nám mění počet. update_count(model, view) dělá view.SetLabel(str(len(model))).

        self.mapper.add_route("/", "", self.on_product,)
        self.model.add_listener(self.mapper)

Zde mám jistou pochybnost, jestli by změna model.article neměla spíš vystřelovat s cestou /article, a změna model.sn s cestou /sn místo cesty / a parametru key. No, ještě si to rozmyslím.

view02.py

Tohle je vpodstatě totéž, až na to, že máme lepší MVCList, který opravdu obsluhuje jednotlivé události zvlášť.

Postup a operace do jedné tabulky

Co když nechceme zobrazit obě tabulky, ale stačí nám postup s indikací toho, které operace již byly vykonány? Inu, model je pořád stejný, na něm se logicky nic nemění, ale musíme si upravit view: view03.py. Základem bude specializovaná tabulka (ProcView), potomek MVCView, která normálně reaguje na změny v model.process, ale při změně model.process nebo model.operations navíc ještě nastaví hodnotu ve sloupci Done.

Když budete mačkat tlačítko Add Operation jako diví, tak se vám postupně budou hodnoty ve sloupci Done měnit na YES. No, a to by na ukázku mohlo stačit.

Příště

Nedávno jsem na jednom fóru viděl radu používat pro přístup k hodnotám a pro změnu hodnot settery a gettery, a totéž mi radil kdosi v komentářích pod minulým dílem. Upřímně hned řeknu, že se mi to moc nelíbí, protože struktura modelu bude odpovídat struktuře view jen v těch nejjednodušších případech, ale dám tomu šanci.