Folytatjuk az előző bejegyzésekben elkezdett Excelszerű egyszerű számolótábla megvalósítását. Legutóbb a cellatartalom kiértékelését végző eseménykezelőt implementáltuk. Most annak az eseménykezelőnek a kidolgozásával kezdjük, amellyel egy egéresemény bekövetkeztekor meg tudjuk jeleníteni a cellában levő képletet (kifejezést), ha volt ilyen. Ennek felhasználásával utána a táblázat cellaértékeinek aktualizálását végző eseménykezelőt is lekódoljuk.
Az előző bejegyzésekből már ismert, hogy az adott cellához tartozó képlet megjelenítését konkrétan a reveal_cell_expression_event_handler() eseménykezelő függvénnyel kívánjuk megvalósítani, ami a bal egérgomb dupla kattintásának hatására fut le. Ekkor a következő műveleteket hajtjuk végre:
1) Meghatározzuk az eseménnyel érintett beviteli mező objektumot.
2) E beviteli mezőhöz rendelt kontrollváltozót és az eltárolt kifejezést kikérjük az ezeket tartalmazó szótárból. Ehhez felhasználjuk a már megvalósított és rendelkezésre álló get_cell_indexes() függvényt, amely a beviteli mező grid elrendezésbeli sor- és oszlopindexeit adja vissza egy tuple objektumban.
3) Ha az adott cellához tartozik kifejezés, vagyis a tárolt érték nem üres karakterlánc, akkor azt megjelenítjük a beviteli mezőben. Ezt az adott beviteli mezőhöz tartozó kontrollváltozó set() metódusának hívásával tehetjük meg, argumentumként a kifejezést reprezentáló karakterláncot adva.
4) Végül, a beviteli mezőben megjelenő tartalom végére állítjuk a kurzort a beviteli mezőre meghívott icursor() metódussal.
A fenti lépéseket két részletben valósítjuk meg. A reveal_cell_expression_event_handler() eseménykezelő az 1) lépés után meghív egy segédfüggvényt reveal_cell_expression néven, amely a 2)-4) pontokban foglaltakat hajtja végre. E két függvény definícióját mutatjuk alább. Arra, hogy miért bontottuk ketté a megvalósítást két függvénybe mindjárt választ adunk.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
import tkinter as tk root = tk.Tk() # A táblázat adott pozíciójában levő beviteli mezőhöz (entry box) tartozó kontrollváltozót és képletet tároló szótár. ebx_vars = {} def eval_cell_content(entry_widget):... def get_cell_indexes(entry_widget)->tuple[int,int]:... def reveal_cell_expression_event_handler(e): """Az eseménnyel érintett beviteli mezőhöz tarozó képlet megjelenítése a mezőben.""" ebx = e.widget # Az eseménnyel érintett beviteli mező. reveal_cell_expression(ebx) def reveal_cell_expression(entry_widget): # A beviteli mezőhöz rendelt kontrollváltozó és az eltárolt kifejezés kikérése az ezeket tartalmazó szótárból. ebx_var, expression = ebx_vars.get(get_cell_indexes(entry_widget)) # Ha tartozik az adott cellához kifejezés (nem üres a karakterlánc), akkor azt megjelenítjük a beviteli mezőben. if expression: # Az eseményyel érintett beviteli mezőhöz tartozó kontrollváltozó értékének a kifejezést adjuk. ebx_var.set(expression) # A beviteli mezőben a kurzort a kifejezés végére állítjuk. entry_widget.icursor('end') def update_expressions(e): """A táblázat minden cellájában aktualizálja a képlet értékét.""" for ebx in e.widget.master.grid_slaves(): reveal_cell_expression(ebx) eval_cell_content(ebx) # Táblázatrács kirajzolása. # ... # Események és eseménykezelők összerendelése és beviteli mezőkhöz kötése. root.bind_class('Entry', '<Double ButtonPress 1>', reveal_cell_expression_event_handler) root.bind_class('Entry', '<Key Return>', update_expressions, add=True) root.bind_class('Entry', '<FocusOut>', update_expressions, add=True) # ... root.mainloop() |
Miután elő tudjuk hívni egy cellához eltárolt képletet, könnyen meg tudjuk valósítani a táblázat cellatartalmainak aktualizálását, azaz képleteinek újraértékelését, ha valamely cella értékében változás történne. Ehhez nem kell mást tenni, mint
a) végigvenni a táblázat celláit (beviteli mező objektumait),
b) minden egyes beviteli mezőre kikérni a hozzá tartozó képletet,
c) a már implementált és rendelkezésre álló eval_cell_content() metódussal kiértékeljük a képletet és eredményét megjelenítjük a cellában.
Látjuk, hogy a b) pontban nem esemény, hanem az éppen aktuális beviteli mező alapján kérjük ki a cella tárolt képletét. Ezért volt értelme külön definiálni a reveal_cell_expression() függvényt, mert az argumentumként beviteli mezőt vár.
A fenti a)-c) pontok alapján a cellák kifejezéseinek aktualizálását végző update_expressions() metódus definícióját szintén fent láthatjuk a jelen bejegyzéshez releváns esemény-eseménykezelő hozzárendelésekkel együtt.
A következő bejegyzésben azon eseménykezelőket valósítjuk meg, amelyek lehetővé teszik a kurzor más cellába áthelyezését, a cella tartalmának törlését, valamint az oszlopszélesség igazítását a cella tartalom hosszához.
E bejegyzéshez a Python tudásépítés lépésről lépésre című e-könyvben különösen a következő részeket érdemes átnézni: „Grafikus felhasználói felület készítése” fejezet „Kontrollváltozók” és „A grafikus elemek fajtái, létrehozásuk és konfigurálásuk” alfejezete, és ebben a „Beviteli mező” alcím.