Ha a grafikus felhasználói felületen megjelenő bizonyos szövegeket figyelemfelkeltővé vagy a szokásostól eltérő kinézetűvé akarjuk tenni, akkor ennek egy módja lehet, hogy a szöveget pontmátrix karakterekkel jelenítjük meg.
A pontmátrix karakter olyan szimbólumot jelent, amely kétdimenziós rácsba rendezett pontok mintázataként jelenik meg.
Ahhoz, hogy ilyen, pontmátrix karakterekből álló szövegeket megjelenítsünk két dologra van szükség. Egyrészt meg kell tervezni a karakter képét, majd elő kell állítani a használni kívánt karakterek valamilyen mátrix-reprezentációját és végül azokat alkalmas módon eltárolni egy fájlban. Másrészt egy ilyen pontmátrix karakter leíró fájlban tárolt adatok alapján ki kell rajzoltatni a szöveg egyes karaktereit a grafikus felületen. Ennek folyamatát szemlélteti ez az ábra:

Elsőként tehát egy karaktertervező alkalmazást kell készíteni.
A karakterkép tervezését, mivel ez egy egyéni vizuális alkotás, grafikus felületen lehet hatékonyan megtenni. Tehát a programnak egy mátrix rácsozatot kell biztosítani, amelyben egyszerű módon (pl. egérgomb kattintással) ki lehet jelölni (pl. színváltással) a karakterképben megjelenítendő cellákat. Ez lesz a tervezőrács. Lehetőséget kell biztosítani arra, hogy a tervező eldöntse, hogy a karaktereket milyen sor és oszlop méretű rácsozatban kívánja előállítani. Ez a használni kívánt karakterkészlettől is függ, de mindenképpen szempont, hogy a megjelenített karaktereknek egyértelműen és jól felismerhetőnek kell lenniük. Ezért a kevesebb sorszám, vagyis alacsonyabb magasság (pl. 5×7, azaz 5 oszlop és 7 sor) összetettebb karaktereknél (pl. ékezetes betű), nem lesz megfelelő. Az 5×12 méret bizonyul olyannak, amelyekkel már az ékezetes nagybetűk és az írás fővonala alá nyúló betűk is jól megjeleníthetők. Ezért alapértelmezésben ezt alkalmazzuk.
Ha a tervezéssel megvagyunk, akkor a tervezőrács vizuális tartalmát le kell képezni egy mátrixba. Ez a mátrix speciális abban az értelemben, hogy csak két értéket tartalmaz, célszerűen 0 és 1, ahol a 0 jelenti a nem kijelölt, üres cellát. A mátrix kódbeli megvalósítása számos módon lehetséges. Mi most azt választjuk, hogy a mátrix sorai olyan karakterláncok, amelyek csak ’0’ és ’1’ számjegykaraktert tartalmaznak, és hosszuk azonos, a mátrix oszlopszámával megegyező. E karakterláncokat egy listában tároljuk, ahol a listaindexek a sorindexek. E választás bár nem helytakarékos, de előnye, hogy így a karakterképnek való helyes megfelelés ellenőrzése vizuálisan is megtehető.
Ahhoz, hogy tudjuk, hogy e mátrix-reprezentáció melyik karakterhez tartozik, a karaktert és a mátrixot egymáshoz kell rendelni. Ezt egyszerűen egy szótárban valósítjuk meg, ahol a kulcsok a karakterek, a hozzájuk tartozó értékek az előbb említett listák, amelyek elemei a ’0’ és ’1’ jegyeket tartalmazó karakterláncok.
A tervezés eredményét a későbbi használathoz el kell tárolni. Ezt is több módon lehet megtenni, de mivel szótárról van szó, így a JSON formátum tűnik célszerűnek a könnyű kódolás és dekódolás miatt, hiszen a szótár egyszerűen egyetlen JSON objektumba képződik le.
Ami a tárolt pontmátrix karakterkészlet használatát, megjelenítését illeti, első lépésben a leíró JSON fájl tartalmát beolvassuk egy szótárba. Ezután vesszük a megjelenítendő szöveg egyes karaktereit és kikérjük a szótárból a hozzá tartozó mátrix-reprezentációt. Ennek alapján egy vászon (Canvas) elemen körökkel vagy négyzetekel kirajzoljuk a mátrixpontokat, majd az egyes vásznakat egymást követően lehelyezzük egy keretben (Frame). E keretet tudjuk aztán a főablakban vagy máshol elhelyezni, és így a szöveget megjeleníteni.
A fenti elvek alapján készített alkalmazás forráskódját különböző modulokba szervezve láthatjuk alább. A megértést a részletes kommentek segítik.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# modul: until.py from pathlib import Path import json def save_dotmatrix_charset_json(dotmatrix_charset: dict, filepath: str | Path): """Az argumentumban megadott szótárat elmenti egy JSON fájlba a megadott útvonalon és névvel.""" with open(Path(filepath), 'w', encoding='UTF8', newline='\n') as f: json.dump(dotmatrix_charset, f) def read_dotmatrix_charset_json(filepath: str | Path) -> dict: """Az argumentumban megadott útvonalon elérhető JSON fájl tartalmát beolvassa egy szótárba.""" if Path(filepath).stat().st_size == 0: # Ha a fájl létezik, de üres, akkor egy üres szótárat adunk vissza. return dict() with open(Path(filepath), 'r', encoding='UTF8', newline='\n') as f: d = json.load(f) return d |
|
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# modul: dotmatrixstring_widget.py import tkinter as tk from util import read_dotmatrix_charset_json class DotMatrixString(tk.Frame): """Az osztály egy példánya az inicializáláskor a string_to_display paraméternek átadott karakterláncot pontmátrix formában jeleníti meg egy Frame objektumon úgy, hogy az egyes karakterek egymást követően lehelyezett Canvas elemeken vannak kirajolva. Azt, hogy hogyan jelenjenek meg a karakterek a filepath argumentumban megadott pontmátrix-leíró JSON fájl tartalma határozza meg. Az inicializáláskor az fg és bg opcionális argumentumokkal megadható a szöveg- és háttérszín, valamint az, hogy a mátrixpontok körrel vagy négyzettel legyenek megjelenítve. Ha négyzettel, akkor a marker paraméternek a "rectangle", ha körrel, akkor a "circle" értéket kell adni. Ez utóbbi az alapértelmezett. A karakterek alapértelmezésben a beolvasott pontmátrix leíró fájlban szereplő sor- és oszlopszám szerinti pixel méretben jelennek meg (pl. 5x12 pixel), de ennek egész számú többszörösére nagyíthatók a scale_factor beállításával. """ def __init__(self, master, string_to_display: str, filepath: str, bg='white', fg='black', scale_factor=1, marker='circle'): super().__init__(master) # Beolvassuk a megadott JSON fájlból a pontmátrix karakterkészletet egy szótárba, ahol a kulcsok az egyes # karakterek, a kulcsokhoz tartozó értékek pedig egy-egy lista, amely a karakter pontmátrix leírását # tartalmazza '0' és '1' karakterekből álló karakterláncok formájában. Ezek száma a pontmátrix sorainak # számával egyenlő, a karakterláncok hossza pedig a pontmátrix oszlopainak számával egyezik. self.charset: dict = read_dotmatrix_charset_json(filepath) # A beolvasott szótár alapján meghatározzuk a karakterek méreteit, azaz a mátrix sor- és oszlopszámát. a_bitmx = self.charset[list(self.charset)[0]] self.rowcount, self.columncount = len(a_bitmx), len(a_bitmx[0]) for char in string_to_display: # A megjelenítendő karakterlánc egyes karaktereit egy-egy vászon elemen kirajzoljuk, és a vásznakat # egymást követően lehelyezzük a keretben. charmx: list[str] = self.charset.get(char, self.charset.get(chr(0xfffd))) canvas = tk.Canvas(self, bg=bg, highlightthickness=0) canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) for ri, bitstring in enumerate(charmx): bitstring: str # Az egy sorban levő '0' vagy '1' tartalmú karakterlánc. for ci, bitchar in enumerate(bitstring): if bitchar == '1': x0, y0 = ci, ri x1, y1 = x0 + 1, y0 + 1 # Az argumentumban megadottnak megfelelően a mátrixpontokat körrel vagy négyzettel jelenítítjük meg. if marker == 'rectangle': canvas.create_rectangle((x0, y0), (x1, y1), tags='dot', fill=fg) if marker == 'circle': canvas.create_oval((x0, y0), (x1, y1), tags='dot', fill=fg) pdx, pdy = 1, 0 # A sor- és oszlopszámhoz igazítjuk a vászon méretét. canvas.config(width=self.columncount + pdx, height=self.rowcount + pdy) # Minden karakterpontot felnagyítunk a megadott mértékkel, és a vászon méretét is ehhez igazítjuk. scalefactor = scale_factor canvas.scale('dot', 0, 0, scalefactor, scalefactor) canvas.config(width=scalefactor * int(canvas.cget('width')), height=scalefactor * int(canvas.cget('height'))) if __name__ == '__main__': # TESZT root = tk.Tk() dotmxfilepath = 'dotmxfonts5x12.json' DotMatrixString(root, 'A tanulás tudás. "A tudás hatalom." (Sir Francis Bacon)', dotmxfilepath, fg='black', bg='light cyan', scale_factor=3, marker='rectangle') DotMatrixString(root, 'PYTHON TUDÁSÉPÍTÉS LÉPÉSRŐL LÉPÉSRE', dotmxfilepath, fg='blue', bg='white', scale_factor=5, marker='circle') DotMatrixString(root, """Az alapoktól az első asztali alkalmazásig.""", dotmxfilepath, fg='red', bg='lightyellow', scale_factor=4, marker='rectangle') for w in root.winfo_children(): w.pack(fill=tk.BOTH, padx=3) root.mainloop() |
|
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
modul: designer.py from __future__ import annotations from itertools import product from pathlib import Path import tkinter as tk from tkinter.scrolledtext import ScrolledText from util import read_dotmatrix_charset_json, save_dotmatrix_charset_json class DesignerGrid(tk.LabelFrame): """Tervezőrácsot megvalósító és megjelenítő osztály""" def __init__(self, master: DotMatrixCharDesigner, rowcount, columncount): super().__init__(master) self.config(text='Karaktertervező rács', labelanchor='n', bg='gray98', font=('Consolas', 12, 'bold')) # A tervezőrács celláit egy-egy négyzet alakú Frame grafikus elem valósítja meg. E cella színe a # bal egérgomb minden egyes lenyomásakor fehér vagy fekete lesz. A fekete jelenti, hogy a cella a # pontmátrixban kijelölt. cell_size = 50 # Egy rácscellát reprezentáló keret mérete. for ri, ci in product(range(rowcount), range(columncount)): cell_frame = tk.Frame(self, name='cell' + '{}{}'.format(ri, ci), width=cell_size, height=cell_size, bg='white', highlightthickness=cell_size * 0.04) cell_frame.grid(row=ri, column=ci, sticky='news') # A bal egérgomb lenyomása esemény és a színváltást megvalósító eseménykezelő cellákhoz rendelése. cell_frame.bind('<Button 1>', self.toggle_cell_color) def toggle_cell_color(self, event): """A tervezőrács egy adott, az eseménnyel érintett cellája színváltását megvalósító eseménykezelő.""" widget: tk.Frame = event.widget widget.config(bg='black' if widget.cget('bg') == 'white' else 'white') def clear(self): """Törli a tervezőrács tartalmát, vagyis minden cellát fehér színűre állít.""" for cell_frame in self.winfo_children(): cell_frame.config(bg='white') class FileContentViewer(tk.LabelFrame): """Az aktuális karakterkészlet pontmátrix definícióit hordozó fájl tartalmának megtekinthetőségét megvalósító osztály""" def __init__(self, master: DotMatrixCharDesigner): super().__init__(master) self.config(text='Fájltartalom', labelanchor='n', bg='gray98', font=('Consolas', 12, 'bold')) # A fájltartalmat egy függőleges görgetősávval ellátott Text típusú grafikus elemmel jelenítjük meg, amit a # a tkinter modulban rendelkezésre álló ScrolledText osztállyal valósítunk meg. self.filecontent = ScrolledText(self, bg='gray98', font=('Consolas', 10), width=115) self.filecontent.pack(fill=tk.BOTH, side=tk.LEFT, expand=True, padx=5, pady=5) # Az aktuális karakterkészletet tartalmazó szótár kulcs-értékpárjait írjuk egymás alá a ScrolledText elemben. txt = '\n'.join([f'{key}:{value}' for key, value in master.charset.items()]) self.filecontent.insert('1.0', txt) class ToolBar(tk.Frame): def __init__(self, master: DotMatrixCharDesigner): super().__init__(master) common_configs = dict(font=('Consolas', 14, 'bold')) # A grafikus elemek azonos konfigurációs paraméterei. # A megtervezni kívánt karakter beviteli mezője a hozzárendelt kontrollváltozóval. self.char = tk.StringVar(self, '') tk.Entry(self, textvariable=self.char, width=3, justify=tk.CENTER, font=('Consolas', 24, 'bold')) # Nyomógomb a beviteli mezőben megadott karakter pontmátrix képének tervezőrácsban történő megjelenítéséhez. tk.Button(self, text='Betölt', **common_configs, command=lambda: master.show_char_in_designer_grid(self.char.get())) # Nyomógomb a tervezőrács tartalmának törléséhez, ami a cellák fehérre váltását jelenti. tk.Button(self, text='Rácstörlés', **common_configs, command=master.designer_grid.clear) # Nyomógomb a beviteli mezőben megadott karakter karakterkészletből történő eltávolítására. tk.Button(self, text='Eltávolítás', **common_configs, command=lambda: master.remove(self.char.get())) # Nyomógomb a beviteli mezőben megadott karakter és a tervezőrácsban szereplő pontmátrix definíciójának # karakterkészletbe történő felvételére és fájlba mentése. tk.Button(self, text='MENTÉS', **common_configs, command=master.update_and_save_charset) # A fenti grafikus elemek lehelyezése azonos paraméterekkel. for widget in self.winfo_children(): widget.pack(side=tk.LEFT, padx=(2, 2), pady=5) # A karakterkészletet tároló fájl útvonalának és nevének megadására szolgáló beviteli mező. filepath_ebx = tk.Entry(self, textvariable=master.filepath, width=40, justify=tk.LEFT, font=('Consolas', 18)) filepath_ebx.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(5, 5), pady=7) class MessageBar(tk.Frame): """A tájékoztató vagy hibaüzeneteket megjelenítő sávot megvalósító osztály.""" def __init__(self, master: DotMatrixCharDesigner): super().__init__(master) # A kiírandó szövegek egy Label típusú grafikus elemen jelennek meg, amelyhez egy, az aktuális szöveget # tartalmazó kontrollváltozó van társítva. self.message = tk.StringVar(self, '') lbl_msg = tk.Label(self, textvariable=self.message, bg='gray95', fg='red', font=('Consolas', 12, 'bold')) lbl_msg.pack(fill=tk.BOTH) class DotMatrixCharDesigner(tk.Tk): """Pontmárix karakterek tervezésére szolgáló alkalmazás. A példányosításkor meg kell adni egy fájlt a charset_filepath paraméternek, amelybe a megtervezett karakterek és pontmátrix leírásuk JSON objektumként kerül. Ha a megadott fájl egy létező pontmátrixleíró JSON fájl, akkor ennek tartalma beolvasásra kerül feltéve, hogy az nincs ellentmondásban a tervezendő pontmátrix sor- és/vagy oszlopméretével, amelyet a rowcount és columncount argumentumokkal lehet meghatározni. Sikeres beolvasás után a fájl tartalma megjelenik a jobb oldali keretben, ami segít megállapítani, hogy mely karakterek vannak már megtervezve. Ha pedig egy karaktert szerkeszteni akarunk, akkor megadva a karaktert a bal alsó beviteli mezőben, a hozzá tartozó pontmátrix betölthető és megjeleníthető a tervezőrácsban a "Betölt" gomb megnyomásával. A tervezőrácsban a bal egérgomb kattintással lehet a mátrixpontokat ki/be kapcsolni. Akár új karaktert, akár meglévőt szerkesztünk a rácsban, ha befejeztük, akkor a "MENTÉS" gomb megnyomásával el kell menteni a tervezés eredményét. Ha pedig egy karaktert a készletből ki akarunk törölni, akkor a karakter beviteli mezőbe írása után az "Eltávolítás" gombra kell kattintani. """ def __init__(self, charset_filepath: str, rowcount: int = 12, columncount: int = 5): super().__init__() self.title('Karaktertervező alkalmazás') self.resizable(tk.NO, tk.NO) self.rowcount, self.columncount = rowcount, columncount # A karaktereket és a megtervezett pontmátrixukat mint kulcs-érték párokat egy szótártárban tartjuk nyilván. self.charset = dict() # Ha a megadott fájlútvonalon érvényes pontmátrixleíró fájl van, akkor annak tartalmát beolvassuk a szótárba. # Ha a fájl nem létezik, akkor a megtervezett karakterek e fájlba fognak mentődni. self.filepath = tk.StringVar(self, charset_filepath) if Path(self.filepath.get()).exists(): self.read_dotmatrixcharset() a_bitmx = self.charset[list(self.charset)[0]] if not (self.rowcount, self.columncount) == (len(a_bitmx), len(a_bitmx[0])): raise ValueError( 'A fájlban szereplő karaktermátrix dimenziója nem egyezik a megadott sor és oszlopszámmal') # A grafikus felület felépítése a komponens keretekből, és ezek lehelyezése a főablakban. self.message_bar = MessageBar(self) self.designer_grid = DesignerGrid(self, rowcount, columncount) self.toolbar = ToolBar(self) self.file_content_viewer = FileContentViewer(self) self.message_bar.grid(row=0, column=0, sticky='wens', columnspan=2) self.designer_grid.grid(row=1, column=0, sticky='wens') self.file_content_viewer.grid(row=1, column=1, sticky='wens', padx=5) self.toolbar.grid(row=2, column=0, columnspan=2, sticky='wens') # Ahhoz, hogy a korábbi tájékoztató üzenet törlődjön, ha a felületen a bal egérgombbal kattintunk. self.bind_all('<Button 1>', lambda e: self.message_bar.message.set('')) def read_dotmatrixcharset(self): """Az aktuális fájlból beolvassa egy szótárba a karakterkészletet. A szótár kulcsai a karakterek, a kulcsokhoz tartozó értékek a karakter pontmátrixleírását tartalmazó listák. """ self.charset: dict = read_dotmatrix_charset_json(Path(self.filepath.get())) def remove(self, char: str): """Az argumentumban megadott karaktert törli a karakterkészletből.""" try: del self.charset[char] save_dotmatrix_charset_json(dict(sorted(self.charset.items())), Path(self.filepath.get())) self.file_content_viewer.filecontent.delete('1.0', tk.END) self.file_content_viewer.filecontent.insert('1.0', '\n'.join([f'{key}:{value}' for key, value in dict(sorted(self.charset.items())).items()])) self.message_bar.message.set(f'A "{char}" karakter törölve lett a karakterkészletből.') self.toolbar.char.set('') except KeyError: self.message_bar.message.set(f'Eltávolítás nem lehetséges, mert a "{char}" karakter nincs definiálva.') self.designer_grid.clear() def show_char_in_designer_grid(self, char: str): """Az argumentumban megadott karakter pontmátrix képét jeleníti meg a tervezőrácsban.""" if len(char) != 1: self.message_bar.message.set('Csak egyetlen, nem üres karakter adható meg!') return # Az eddig elmentett karakterkészlet beolvasása az aktuálisan megadott fájlból. try: self.read_dotmatrixcharset() except FileNotFoundError: self.message_bar.message.set(f'A fájl nem létezik: {self.filepath.get()}') self.charset.clear() self.file_content_viewer.filecontent.delete('1.0', tk.END) return try: # Az aktuális karakterkészletből a megadott karakter mátrixának kikérése. dotmx: list[str] = self.charset[char] except KeyError: # Ha nincs még ilyen karakter a készletben, akkor töröljük a tervezőrács tartalmát, és visszatérünk. self.designer_grid.clear() self.message_bar.message.set('Még nincs ilyen karakter. Ha kell, akkor tervezd meg most.') return # Ha van a karakterkészletben az argumentumban megadott karakter, és így megkaptuk a mátrixát, akkor # a tervezőrács celláit a mátrix értékeinek megfelelő színnel jelenítjük meg. for cell_frame in self.designer_grid.winfo_children(): ri, ci = cell_frame.grid_info()['row'], cell_frame.grid_info()['column'] cell_color = 'black' if dotmx[ri][ci] == '1' else 'white' cell_frame.config(bg=cell_color) def cells_to_matrix(self) -> list[str]: """A tervezőrács tartalmának megfelelő mátrixot hoz létre, amely egy olyan lista, amelynek elemei olyan karakterláncok, amelyek csak '0' vagy '1' karaktereket tartalmaznak aszerint, hogy a tervezőrács adott cellája fehér vagy fekete színű. """ mx: list = [''] * self.rowcount bitstring = '' # Csak '0' vagy '1' karaktereket tartalmazó karakterlánc. for ri, ci in product(range(self.rowcount), range(self.columncount)): row_cells: list = self.designer_grid.grid_slaves(ri) for cell_frame in reversed(row_cells): bitstring += '1' if cell_frame.cget('bg') == 'black' else '0' mx[ri] = bitstring bitstring = '' return mx def update_and_save_charset(self): """A beviteli mezőben megadott karaktert és annak a tervezőrácsban szereplő pontmátrix leírását felveszi a karakterkészletbe és elmenti az aktuálisan megadott fájlba. """ if len(self.toolbar.char.get()) == 1: self.charset.update({self.toolbar.char.get(): self.cells_to_matrix()}) # A szótárat egy JSON fájlba mentjük. save_dotmatrix_charset_json(dict(sorted(self.charset.items())), Path(self.filepath.get())) # A fájltartalom megjelenítését aktualizáljuk. self.file_content_viewer.filecontent.delete('1.0', tk.END) content_text = '\n'.join([f'{key}:{value}' for key, value in dict(sorted(self.charset.items())).items()]) self.file_content_viewer.filecontent.insert('1.0', content_text) # Tájékoztató üzenet az elmentésről. self.message_bar.message.set(f'A "{self.toolbar.char.get()}" karakter el lett mentve.') else: self.message_bar.message.set('Csak egyetlen, nem üres karakter menthető!') def run(self): self.mainloop() if __name__ == '__main__': designer = DotMatrixCharDesigner('dotmxfonts5x12.json') designer.run() |
A karaktertervező felülete négy fő tartományra tagolódik:
- a tervezőrács,
- a megtervezett karakterkészletet tároló fájl tartalmát mutató rész,
- egy üzenetsáv, amelyen vagy hibaüzenetek vagy az egyes műveletekről való visszajelzés jelenik meg, valamint
- egy eszköztárnak is nevezhető rész, ahol a következők helyezkednek el:
- az egyes végezhető műveleteket indító gombok
- egy beviteli mező a tervezendő karakter számára,
- egy beviteli mező, ami a fájl megadására szolgál.
Mind a négy tartományt egy-egy osztály valósítja meg.
A designer modul DotMatrixCharDesigner osztályának példánya jelenti a pontmátrix formában megjelenő karakterek tervezését lehetővé tevő alkalmazást. Az osztály példányosításakor meg kell adni egy fájlt a charset_filepath paraméternek, amelybe a megtervezett karakterek és pontmátrix leírásuk kerül JSON objektumként. Ha a megadott fájl egy létező pontmátrixleíró JSON fájl, akkor ennek tartalma beolvasásra kerül feltéve, hogy az nincs ellentmondásban a tervezendő pontmátrix sor- és/vagy oszlopméretével, amelyet a rowcount és columncount argumentumokkal lehet meghatározni.
Sikeres beolvasás után a fájl tartalma megjelenik a jobb oldali címkézett keretben, ami segít megállapítani, hogy mely karakterek vannak már megtervezve. Ha pedig egy már elmentett karaktert szerkeszteni akarunk, akkor megadva a karaktert a bal alsó beviteli mezőben, a „Betölt” gomb megnyomásával a hozzá tartozó pontmátrix betölthető és megjeleníthető a tervezőrácsban.
A tervezőrácsban bal egérgomb kattintással lehet a mátrixpontokat ki/be kapcsolni, és így a fekete színű cellákkal a karakter formáját kialakítani.
Akár új karaktert, akár egy már meglévőt szerkesztünk a rácsban, ha befejeztük, akkor a „MENTÉS” gomb megnyomásával el kell menteni a tervezés, illetve szerkesztés eredményét.
Ha egy karaktert a készletből ki akarunk törölni, akkor a karakter beviteli mezőbe történő írása után az „Eltávolítás” gombra kell kattintani.
A dotmatrixstring_widget modulban található DotMatrixString osztály egy példánya az inicializáláskor a string_to_display paraméternek átadott karakterláncot pontmátrix formában jeleníti meg egy Frame objektumon úgy, hogy az egyes karakterek egymást követően lehelyezett Canvas elemeken vannak kirajolva. Azt, hogy hogyan jelenjenek meg a karakterek a filepath argumentumban megadott pontmátrix-leíró JSON fájl tartalma határozza meg.
Az inicializáláskor az fg és bg opcionális argumentumokkal megadható a szöveg- és háttérszín, valamint az, hogy a mátrixpontok körrel vagy négyzettel legyenek megjelenítve. Ha négyzettel, akkor a marker paraméternek a „rectangle”, ha körrel, akkor a „circle” értéket kell adni. Ez utóbbi az alapértelmezett.
A karakterek alapértelmezésben a beolvasott pontmátrix leíró fájlban szereplő sor- és oszlopszám szerinti pixel méretben jelennek meg (pl. 5×12 pixel), de ennek egész számú többszörösére nagyíthatók a scale_factor beállításával.
A karaktertervező alkalmazás felületének képernyőképe, valamint a dotmatrixstring_widget modulban található tesztsorok eredménye látható alább:

A teljes forráskód elérhető ezen a Github linken: https://github.com/pythontudasepites/dotmatrix_character_designer
A futtatáshoz Python 3.10+ verzió szükséges.
Ebben az alkalmazásban a GUI felület kialakítása és a fájlműveletek voltak a hangsúlyosak. Ezekről a tudnivalókat a Python tudásépítés lépésről lépésre című e-könyvben részletesen a „Grafikus felhasználói felület készítése” és a „Mentsük, ami menthető! – fájlok és mappák” című fejezetek tartalmazzák. Természetesen az alkalmazás számos más nyelvi ismeretet is igényel, amelyeket az e-könyv egyéb fejezetei szintén részletesen tárgyalják.