Přeskočit na obsah

Tkinter/Otázky a odpovědi

Z Wikiverzity
Jak používat klasifikační nálepkuTato stránka je součástí projektu:
Příslušnost: Juandev

Doplňový studijní nástroj pro seznámení se s Tkinter slouží jako doplnění Vašeho osobního studia. Používá se tak, že si zde zapisujete otázky a sami si k nim na internetu (chatGPT, YouTube, diskusní skupiny) hledáte odpovědi, které pak také zapíšete. V rámci procvičování porozumění danému tématu můžete také zodpovědět otázky, bez odpovědí.

Nástroj má tři sekce. V první jsou všemožné otázky a odpovědi týkající se knihovny Tkinter. Do druhé se dávají chybové hlášení a jejích řešení. Poslední sekce je věnována souvisejícím problémům.

Otázky a odpovědi

[editovat]

Do této tabulky patří všemožné otázky týkající se knihovny Tkinter. Kód se označuje jako kód nebo blok kódu v nástrojích vizuálního editoru. Můžete připojit i soubory nákresů.

Č. Otázka Odpověď Poznámky
OO.1 Proč je metoda Grid() navázána na Widget Entry? Grid() není metoda, ale geometrický manager. Každý widget (jako např. Entry()) má k dispozici různé geometrické managery dle logiky věci. Znanemá to, že existují widgety, které nemají k dispozici všechny geometrické managery.
OO.2 Jaké jsou typy managerů geometrie?
  1. pack()
    • zabalí widgety vedle sebe a při změnách okna je překreslí tak, aby zabíraly co nejmenší plochu
    • organizace probíhá zeshora nahoru a zleva doprava
    • využívá se u jednoduších rozvržení
    • definuje se to pro každý widget zvlášť a tak se to dá i pro každý widget zadávat jinak
    • dostupné parametry:
      1. side - určuje od které strany se prvky za sebe zařadí. default je top, takže nahoře je první prvek, pod ním druhý a tak dále. Pokud bysme ale třeba chtěli pořadí otočit, pak zadám parametru side hodnotu bottom (.pack(side = "bottom"). Hodnotami side jsou tedy top, right, bottom a left.
      2. fill - má hodnoty x, y, both a none, kde hodnota none je výchozí, takže, když není parametr fill zadán, tak widget nevyplňuje to co by vyplňovat mohl. Both znamená, že vyplní možný prostr všemi směry, x horizontálně a y vertikálně. Zadání by bylo následující: .pack(side = "bottom", expand = True, fill = "both"). Bokud by byla hodnota expand False, stále je možné vyplnit prostor ve směru kolmém na směr zadání dle side.
      3. expand - je Boolean parametr (hodnoty True, False), který určuje, jestli widget může zabítat celý možný prostor ve směru definovaném v side. Default je False, což znamená, že pomyslný borderline widgetu je tak velký, aby se do něj vešel pouze například text. Pokud zadáme expand True, otevře se možností zvětšit bordreline widgetu na maximální možný rozsah. Takže například: .pack(side = "bottom", expand = True. Nicméně je to jenom možnost, samotné vyplnení celého prostoru se musí dořešit parametrem fill. Takže se jedná o jakýsi zámek směru vyplnění.
      4. anchor - v tomto případě kontva posouvá text (obsah widgetu ve směru jaký je definován) zatímco samotný widget zůstává na místě.
  2. grid()
    • rozčlení pole na sloupce a řádky, do kterých se vkládají jednotlivé widgety
    • používá se u složitějších rozložení
    • dostupné parametry jsou:
      1. row
      2. column
      3. rowspan - definuje přes kolik řádků se může blok widgetu rozptrostřít
      4. columnspan - definuje přes kolik sloupců se může blok widgetu rozprostřít
      5. sticky - definuje, ke které straně se může pomyslný borderline widgetu v rámci buňky gridu přilepit. Normálně je uprostřed a není přilepen k žádné straně. Hodnoty n (z anglického north - sever), e (east - východ), s a w mohou widgetu umožnit se přilepit z různých stran. Pokud se zadá kombinace, napříkad ns, widget se může roztáhnout, aby se přilepil nahoru a dolu, nicméně šířka zůstane v šířce obsahu widgetu, např. textu. Pokud tedy zadáme sticky = "nesw", tak se nám pomyslný borderline roztáhne, respetive umožní roztažení do celé buňky v tabulce (gridu).
      6. padx - vytváří prostor kolem widgetu v horizontální ose
      7. pady - vytváří vertikální prostor kolem widgetu
      8. ipadx, ipady - rozšiřuje pomyslný borderline widgetu po ose x (horizontální), nebo y (vertikální)
  3. place()
    • stanovuje přesnou pozici prvku v pixelech
    • umí též umístit a zafixovat celé okno na obrazovce
    • umožňuje relativní i absolutní pozicování
    • dostupné parametry:
      1. x
      2. y
      3. width
      4. height
      5. anchor - určuje ke kterému bodu widgetu se bude vztahovat vzdálenost od výchozího bodu. Možné hodnoty jsou 'n', 'ne', 'e', 'se', 'sw', 'w', 'nw' a "center". anchor = "nw" je default, takže se nemusí zapisovat.
      6. bordermode
      7. relheight, relwidth
      8. relx, rely
OO.3 Je možné absolutní rozležení prvků?
OO.4 Co je to rowspan?
OO.5 Jaký je rozdíl mezi rowspan a columnspan?
OO.6 Je place() metoda? Ano, viz: tutorialspoint.com/python/tk_place.htm.
OO.7 Jak se pracuje z columnconfigure()?
OO.8 Co je to frame?
OO.9 Jak rozumět zápisu: {'background': ('background', 'frameColor', 'FrameColor', '', ''), 'foreground': ('foreground', 'textColor', 'TextColor', '', ''), 'font': ('font', 'font', 'Font', '', ''), 'borderwidth': ('borderwidth', 'borderWidth', 'BorderWidth', '', ''), 'relief': ('relief', 'relief', 'Relief', '', ''), 'anchor': ('anchor', 'anchor', 'Anchor', '', ''), 'justify': ('justify', 'justify', 'Justify', '', ''), 'wraplength': ('wraplength', 'wrapLength', 'WrapLength', '', ''), 'takefocus': ('takefocus', 'takeFocus', 'TakeFocus', '', ''), 'text': ('text', 'text', 'Text', '', ''), 'textvariable': ('textvariable', 'textVariable', 'Variable', '', ''), 'underline': ('underline', 'underline', 'Underline', -1, -1), 'width': ('width', 'width', 'Width', '', ''), 'image': ('image', 'image', 'Image', '', ''), 'compound': ('compound', 'compound', 'Compound', '', ''), 'padding': ('padding', 'padding', 'Pad', '', ''), 'state': ('state', 'state', 'State', <index object: 'normal'>, <index object: 'normal'>), 'cursor': ('cursor', 'cursor', 'Cursor', '', ''), 'style': ('style', 'style', 'Style', '', ''), 'class': ('class', '', '', '', '')}? Jedná se o slovník, který obsahuje v kulatých závorkách pro jednotlivé možnosti (options) n-tice (tuple). Jednotlivé pozice v ntici, od první:
  1. název možnosti
  2. název možnosti v databázi (moc se nepoužívá)
  3. třída názvu možnosti v databázi (moc se nepoužívá)
  4. výchozí hodnota
  5. současná hodnota možnosti
OO.10 Jak zjistím jaké jsou volitelné hodnoty pro možnosti metody .configure()? Například v Tk docs hledat "configuration options" v jednotlivých widgetech.
OO.11 Mohu metodou get() získat text z popisu widgetu Label? Možná, v nápovědě příkazu gets jazyka Tcl je napsáno, že sbírá data pouze z kanálů (tj. stdin, stdout a stderr). Proč se zde odkazujeme na nápovědu jazyka Tcl je vysvětleno v řádce 12.
OO.12 Existuje nějaká one page documentace pro Tkinter? Ne. Je to jako Vicuna, někdo vyvine skvělou aplikaci, ale pak ji nejsme schopni plně užíváte, protože nevíme co jak funguje. Dobře mohou posloužit tyto odkazy

Dále možnosti konfigurace jednotlivých widgetů se hledají přes "configuration options" v Tk docs pro každý widtet zvášť.

OO.13 Jak zjistím jakou mám verzi Tcl?
import tkinter as tk

tcl_version = tk.TclVersion

print("Tcl Version:", tcl_version)
OO.14 Kdy vyšla verze Tcl 8.6? V prosinci 2012.
OO.15 Je get() metoda z tkinter? Zdá se že ano.
OO.16 Co je to <index object: 'normal'> v otázce číslo 9?
OO.17 Jak vypíšu hodnoty pro možnosti?
OO.18 Je kanálem stdin můj vlastní skript?
OO.19 Co dělá metoda .StringVar()? Metoda StringVar() může držet hodnoty typu řetězec určitého widgetu a podle potřeby je updatovat. Na widget je napojena přes atrribut textvariable. Byť drží hodnoty typu řetězec může přebírat i číselné hodnoty, se kterými pak pracuje jako s řetězci.
OO.20 Jak se zadávají indexy při configurování widgetu s možností underline? Může se zadat pouze jeden index, protože primárně neslouží k podtrhávání textu, ale k něčemu jinému (např. 0 je první index, 1 druhý, atd. Vždy jde zadat ale jen jeden index a zadává se prostě číslem.)
OO.21 Jaké metody jsou podobné tk.StringVar()? IntVar() pro celá čísla, DoubleVar() pro čísla s desetinou čárkou, BooleanVar() pro hodnoty True/False a využívá se hlavně v zaškrtávácích listech. Nicméně i IntVar() umí přenášet řetězce, tzn. pokud se do pole kam je přiřazn IntVar() vloží řetězec, tak ho předává jako řetězec.
OO.22 Jaký je atribut widgetu pro IntVar()? textvariable
OO.23 Jak se řekne česky checkbutton? zaškrtávací pole
OO.24 Jak se řekne česky radiobutton? přepínač
OO.25 Kolik znaků se vejde do widgetu Entry? Limit není, ale může se stanovit, třeba proto, aby se nepřetížil systém, když by někdo do widgetu vkládal velké množství textu. Některé aplikace využívající REPL, mohou ale mít vlastní limitaci.
OO.26 ttk.Checkbutton() atribut value? Nemá, ale stejným způsobem se používá atribut variable.
OO.27 Jak důležité je pořadí atributů ve funkci?
OO.28 Je možné mít v atributu command 2 hodnoty? Ne, ale dá se to docílit tím, že z atributu command volám funkci, která v sobě zahrnuje dvě jiné funkce, které něco dělají.
...

def funkce_1():
    ...

def funkce_2():
    ...

def wrapper_function():
    funkce_1()
    funkce_2()
...

tlacitko = ttk.Button(root, text="Tlačítko", command=wrapper_function).pack()

...
Takže hodnotou atributu command je wrapper_function, která je definávána jako funkce 1 a 2.
OO.29 Může mít onvalue a offvalue dvě hodnoty? Ne
OO.30 Metoda get() na čudlících dává výstupy v podobě 0/1?
OO.31 Jak vypadá hodnota události Motion? <Motion event state=Mod2 x=528 y=255> 1) state=Mod2 znamená, že byl na zařízení Linux stisknutý num lock (ale na každém operačním systému to znamená něco jiného). 2) x=528 znamená, že kurzor je 528 pixelů doprava od horizontálního okraje daného widgetu, a 3) y=255 znamená, že je kurzor 255 px dolů od okraje daného widgetu. Díky 2) a 3) tak lze zjistit pozici kurzoru na widgetu na kterém pozici sleduje událost Motion. Pokud hodnotě Motion přidělíme nějaký placeholder, můžeme pak získávat jednotlivé vlastnosti. Například:
def vyplyvne_hodnotu(motion):
    print(f"Aktivní klávesy: {motion.state}, kurzor se ti propadl až na {motion.y} pixlů.")
Ale pozor, výsledná hodnota motion.state, není Mod2, ale 16, což je bitmask. Děje se tak proto,a by se ušetřili prostředky.
OO.32 Co značí výpis 140227336851328<lambda> objevující se v konzoli při spuštění programu? Je to adresa konkrétní lambda funkce v paměti Pythonu (číslo) a označení, že se jedná o lambda funkci (<lambda>). Python to vypisuje automaticky a má to jen tento význam.
OO.33 Jaký datový typ označují ostré závorky (<>)? Žádný, jedná se o určité formátování.
OO.34 Co je to událost? Jak se do proměnné předávají informace o události? Některé události do proměné předávají datový objekt (např. řetězec), který obsahuje informace, které daný typ události generuje, jindy funkce bind() pouze zapíná následnou funkci (tedy pokud mám například zadán typ události <KeyPress> a následuje funkce print("stisknuto tlačítko") pak v případě kdy s myší umístěnou nad daným widgetem kliknu na klávesnici na jakoukoliv klávesu, tak Tkinter provede danou funkci, tedy vypíše do konzole stisknuto tlačítko. Obecně by se to dalo zapsat jako widget.bind("<označení eventu>", funkce k provedení v případě True na označení eventu). Anglicky se tomu říká event binding, odtud název metody widget.bind(). Vedle této metody umožňuje Tkinter některé události předávat pomocí atributu command.
OO.35 Jak se jmenuje označení eventu (například <Shift>? Typ události (angl. event type).
OO.36 Lze zpracovat označení eventu vícekrát? Ano, ale u druhého zpracování, které jde na nový řádek se musí dát atribut add=+.
OO.37 Proč se mi bindne událost s funkcí při zadání <Shift_L>, ale ne při zadání <Shift>? Protože to tkinter neumí. <Shift> je modifikátor a čeká se, že bude stisknut s něčím, proto musím volit detailní eventy Shift_L (pro stisk levého shiftu) a Shift_R (pro stisk pravého shiftu).
OO.38 Proč detailní události fungují, jen při označení daného widgetu (např. při zadání detailních událostí na widgetu text)? Protože v tkinteru jde připojovat události jen na aktivní widgety. Proto napřed musím kliknout do pole text a pak mohu něco stisknout, aby mi zafungoval typ události. Respetive, pokud bych připojoval události typu pozice kurzoru, pak mi stačí danný widget pouze přejet. Pozice kurzoru (<Motion>) je totiž spojena s myší, kdežto většina ostatních je spojena s klávesnicí a tak jediný způsob aktivace je kliknutím a umístění kurzoru do daného widgetu.
OO.39 Proč mi nic nedělá událost typu <MouseWheel>? Protože mám Linux na kterém je X11 systém a ten událost <MouseWheel> nepodporuje. Místo toho zavádí <Button-4> událost pro scrollování nahoru a <Button-5> pro scrollování dolů.
OO.40 Co je to windowing system?
OO.41 Proč nefunguje <Shift-Button-4>? Protože událost <Shift-Button-4> registruje na systémech X11 (Linux) horizontální pohyb kurzoru. Závisí pak jaký hardware ten horizontální pohyb zajišťuje, tzn. nemusí to být držení klávesy Shift a zároveň otáčení kolečka myši, jak by se mohlo zdát.
OO.42 K čemu je atribut textvariable? Textvariable je atribut, který umožňuje přidat k widgetu proměnou a propojit ji s třídami typu StringVar. To pak umožňuje provádět změny daného hodnoty na obou stranách.
OO.43 Jak se obecně říká třídám jako StringVar, IntVar, DoubleVar apod.? Proměnné knihovny Tkinter (Tkinter variables) či speciální třídy proměných (special variable classes).
OO.44 Proč má událost typu <<ComboboxSelected>> kolem sebe dvě ostré závorky na místo jedné? Protože se jedná o virtuální událost. Byť označení položky v Comboboxu může být provedeno myší, může být zároveň provedeno i touchpedem či programaticky. Není to tedy událost, která by byla svázána s nějakým druhem hardwaru, ale je to tzv. virtuální událost.
OO.45 Proč se dávají typy událostí do ostrých závorek? Je to zejména pro jejich zvýraznění. Když je to v ostrých závorkách, tak je to v Tkinteru nějaká událost. Jedny ostré závorky (<>) označují záznam události, které provedl uživatel fyzicky, dvě ostré závorky (<<>>) pak zaznamenávají abstraktnější akce, proto se jim říká virtuální události.
OO.46 Co se označuje kapitálkama (jako například tk.END jako hodnota atributu index)? Je to konstanta, která představuje koncovou pozici v indexu, nebo widgetu. Tzn. pokud něco vložím do funkce a zároveň tam mám atribut tk.END, tak mi to tu hodnotu vloží na konec výpisu.
...
tabulka.insert(parent= "", index = tk.END, values = ("x", "y", "z"))
...
OO.47 Co je to například ('I046',) při volání table.selection s použitím události <<TreeviewSelect>>? Číslo položky, respetive řádku v tabulce.
OO.48 Co značí atribut a hodnota parent = "" v metodě insert()? Prázdná řetězcová hodnota atributu parent označuje, že hodnoty vládané touto funkcí jsou přivázány ke kořenovému uzlu. Uzly (angl. nodes) v datové vědě obvykle označují bloky textu, nebo dat, na které jsou navázány další uzly. V případě tabulky v treeview je takovým uzlem řádek a kořenovým uzlem je pak první řádek, který ale Tkinter nezobrazuje. Vytváří ho proto, aby z něj udělal "parent node" pro následující "child nodes".
OO.49 Existují v knihovně další konstanty jako END? Ano, například NORMAL (představuje normální stav tlačítka), ACTIVE (představuje stav tlačítka, kdy je s ním prováděna nějaká interakce), NE (směr ukotvení obsahu ve Widgetu), apod.
OO.50 Co je to treeview? Je to grafický widget, který připomíná taxonomický strom obsahující text.
OO.51 Co dělá funkce choice()? Je součástí knihovny random a náhodně vybírá prvky z nějakého souboru.
OO.52 Co dělá funkce selection()? Používá se ve widgetu treeview a vybírá aktuálně vybrané (uživatelem vybrané) položky.
OO.53 Co dělá funkce item()? Na widgetu treeview získává informace o určité položce.
OO.54 Proč je za kulatou závorkou, ještě hranatá: print(tabulka.item(i)["values"])? Protože v kulaté závorce jsou parametry funkce a vždy se dávají do kulaté závorky. A dále proto, že data v položkách widgetu Treeview jsou uloženy ve slovnících a klíče slovníků se volají vložením do hranatých závorek.
OO.55 Co dělá typo funkce <Delete>?
OO.56 Proč má from_ podtržítko? Protože from je klíčové slovo z jádra Pythona, tak aby se to odlišilo.
OO.57 Jaké hodnoty má atribut orient? horizontal, vertical
OO.58 Jak definovat směr odkud se hýbe Progressbar()?
OO.59 Je scrolledtext submodul? Ne, jedná se o modul.
OO.60 Proč je scrolledtext třeba importovat? Protože při importu tkinter neimportujeme celou knihovnu, ale hlavní modul tkinter. Takže se neimportují knihovny, ale pouze moduly. Další moduly je pak potřeba importovat separátně. tkinter knihovna je tedy něco jiného než tkinter modul. Dalšími moduly jsou například scrolledtext, ttk, collorchooser, filedialog a další.
OO.61 Proč se scrolledtext nanaiportuje z knihovnou tkinter? Protože zápis import tkinter as ttk, není importem celé knihovny, ale pouze hlavního modulu tkinter v knihovně tkinter. Jasný zápis by tedy mohl být from tkinter import tkinter as tk, ale to se nepoužívá a místo toho se používá ten zkrácený zápis. Ostatní moduly se neimportují a je tedy potřeba importovat všechny separátně. Proto potřebujeme importovat scrolledtext modul: from tkinter import scrolledtext. Toznamená z knihovny tkinter importuj modul scrolledtext.
OO.62 Proč se mi nezobrazí progressbar při zadání
progressbar_ukol = ttk.Progressbar(
  master = okno,
  orient = "vertical")
?
Pravděpodobně proto, že widget nemá manager geometrie jako pack().
OO.63 Jaký je rozdíl v použití atributů command a variable na widgetu? Atribut command spouští určitou funkci, až v momentě, kdy je jeho Widget aktivován, například poklepáním myší. Mezi widgety, které mají atribut command patří například Button, Checkbutton, Radiobutton a další.

Variable propojuje atribut s hodnotou Tkinter jako StringVar, IntVar, DoubleVar. Pokud je Widget aktivován (vepsáním textu, tažení myší), automaticky se změní hodnota Tkinter hodnoty. Je dostupná jen na některých widgetech jako například Entry, Label, Checkbutton, ale není dostupná pro např. pro Button, Canvas, Text.

OO.64 Která část widgetu progressbar generuje nějaké hodnoty?
OO.65 Má widget progressbar atribut command? Nemá
OO.66 Jaké hodnoty obsahuje ttk.Scale? Jedná se o hodnoty, které jsou ale spojené s pozicí posuvníku, protože se dá udat rozsah hodnot atribut from_ a to.
OO.67 Jak rozumět atributům command a variable v tomto kódu:
skala_float = tk.DoubleVar
skala = ttk.Scale(
  master = okno,
  command = lambda hodnota: print(skala_float.get()),
  from_ = 0,
  to = 25,
  length = 500,
  orient = "vertical",
  variable = skala_float)
skala.pack()
?
Porozumění zobrazuje následující tok zpracování:
OO.68 Co je to metoda pack_propagate()? Nejedná se o metodu, ale konfigurační možnost geometrického manageru pack, zabránit distribuci hodnot width a height z masteru při zadání hodnoty False. Pokud by byla True, nebo by možnost vůbec nebyla zadána, tak se ohraničení volí právě dle následnických widgetů. Tím pádem se vykreslí rozsahy dle následnicích widgetů.
OO.69 Jaké jsou hodnoty atributu side metody pack()? top (výchozí hodnota), right, bottom a left
OO.70 Co je to tk.GROOVE? Jedná se o konstantu definující styl widgetu. Konstantu je možné aplikovat na widgetech, které umožňují konguraci stran jako Button, Frame, Label, Entry, Text, atd. Dalšími konstantami konfigurace stran jsou například tk.FLAT, tk.RAISED či tk.SUNKEN.
OO.71 Co je to konstanta? Je to proměnná, která by se neměla mněnit. To se programátorovi oznamuje tím, že je zapsána kapitálkami. Viz Python/Juandev#Otázky 24.
OO.72 Jak vložím text do widgetu Entry? Metodou insert(). Pokud vkládám widget Entry do proměnné vstup, pak třeba následovně: vstup.insert(0, "text").
OO.73 Co znamená hodnota 0 v metodě insert()? Uvádí index, kam se vloží daný řetězec. Nula je tedy první znak zleva, 1 druhý atd. Pokud by například v poli Entry již byl řetězec FOO, pak následující se následující segment kódu chová následovně:
  • vstup.insert(0, "text") --> textFOO
  • vstup.insert(1, "text") --> FtextOO
  • vstup.insert(2, "text") --> FOtextO
  • vstup.insert(tk.END, "text") --> FOOtext, což je stejné, jakoby jsme zadali vstup.insert(3, "text"), ale hodí se to k tomu abysme nemuseli počítat indexy až dokonce. Navíc ne vždy víme, kolik indexů danný řetězec má.
OO.74 Které widgety navíc má ttk narozdíl od modulu tkinter? Žadné.
OO.75 Ono není nutné přidělovat geometrický manager každému widgetu a stačí ho přidělit jen masterovi? Geometrický manager je nutné přidělovat všem widgetům. Vyjímkou jsou pouze záložky v rámci widgetu ttk.Notebook (toto nefunguje v tkinter.Notebook), které se přidělí metodou notebook.add(child). ttk.Notebook pak automaticky aplikuje managery pack() a grid() na všechny widgety, které volají master Nootebook z metody add(). V příkladu níže, tvoří jednotlivé záložky widgety ttk.Frame (proměnné tab_1 a tab_2). Aby fungovaly jako záložky, nenesou geometrické managery a musí být do ttk.Notebook přidány přes funkci add().
...
notebook = ttk.Notebook(master = okno)

tab_1 = ttk.Frame(notebook)

label_1 = ttk.Label(master = tab_1, text = "Text v záložce 1")
label_1.pack()
tlacitko_1 = ttk.Button(master = tab_1, text "Tlačítko záložky 1")
tlacitko_1.pack()

tab_2 = ttk.Frame(notebook)

label_2 = ttk.Label(tab_2, text = "Text v záložce 2")
label_2.pack()
vstup_2 = ttk.Entry(tab_2)
vstup_2.pack()

notebook.add(tab_1, text = "Tab 1")
notebook.add(tab_2, text = "Tab 2")

notebook.pack()
...
Všimněte si, že proměnné tab_1 a tab_2 nemaj explicitně přidělený geometrický manager, zatímco ostatní widgety ano.

To, že je notebook.pack() na konci, nehraje roli. Klidně by mohl být na řádku 3.

OO.76 Jakých atributů může nabývat metoda add()? Jako metoda specifická pro ttk.Notebook nabývá hodnot následník a možnosti. V příkladu na řádku 77 je uvedeno notebook.add(tab_1, text = "Tab 1"). tab_1 je v tomto případě označení následníka widgetu notebook (tab_1 = ttk.Frame(notebook)) a text = "Tab 1" je jedna z možností.
OO.77 Kolik generací následovníků může zdědit pack()? V podstatě žádnou. Jde zde pouze o to, že u widgetu ttk.Notebook se nemusí do kódu pro každou záložku definovanou widgetem ttk.Frame (ani jakýmkoliv jiným widgetem jako např. tkinter.Frame či ttk.Button) uvádět pack(), protože se to aplikuje z třídy Notebook po přidání widgetu následovníka do masteru přes funkci add().
OO.78 ttk.Frame nemá atribut text? Nemá, takže pokud využívám ttk.Frame pro tvorbu záložek v ttk.Notebook a chci jim dát nějaký text, musím využít metody add() (která je metodou ttk.Notebook) a vložit tam text takto.
...
notebook = ttk.Notebook(master = okno)
notebook.pack()

#Záložka 1
tab_1 = ttk.Frame(master = notebook)

#Metoda add() vkládá text do widgetu Frame
notebook.add(tab_1, text = "Toto je záložka 1")
...
OO.79 Jaké funkce má metoda add()? Metoda přidává následovníka do masteru, tedy do widgetu ttk.Notebook. Navíc do widgetu následníka může vkládat text či obrázek.
OO.80 Jaký je rozdíl mezi tk.Menu a ttk.Menu?
OO.81 Jaký je rozdíl mezi Menu a Treeview? Oba widgety jsou v určitém smyslu podobné, nicméně Treeview se využívá hlavně pro zobrazení kořenové strkutury, jakou je třeba struktura adresářů, kdežto Menu jsou spíše obdélné záložky, které se sice také mohou větvit, ale z principu jde spíše o to záložkové zobrazení a poskytnutí odkazů na další funkce a text.
OO.82 Co dělá okno.configure(menu = menu)? Odkazuje na widget menu na hlavním okně, který se má chovat jako vyskakovací položka. Jinak řečeno menu nalevo je placeholder pro atribut, pravé menu je hodnota, v tomto případě proměnná, kterou je definován Menu widget: menu = tk.Menu(master = okno). Takže vyskakovací widget se definuje vždy na nadřazeném widgetu. V tomto případě je nadřazeným widgetem okno definované jako tk.Tk(). Pro definici nadřenzených Záložek se ale u subzáložek používá metoda add_cascade(), configure() tam nefunguje.
OO.83 Má tk.Menu atribut text? Nemá.
OO.84 Jaké atributy má tk.Menu? ŠPATNÁ ODPOVĚD Pouze tearoff (česky odtrhnout), který má dvě Boolean hodnoty True - vytvoří odtržené menu (které vypadá jako separátní okno), a False, které nutí submenu držet s ostatními ve struktuře. Default je True, takže pro tuto funkcionalitu to není třeba definovat.
OO.85 Proč se nepřidává k tk.Menu geometrický manager? Protože se jeho pozice definuje automaticky. Vytváří řádek v horní části widgetu hlavního okna do něhož se pak vkládají jednotlivé subzáložky (submenu).
OO.86 Co vytváří tk.Menu? De facto kořenové Menu (kořenová záložka), které ale není zobrazeno a zobrazit se nedá. K němu se pak přilepují subzáložky.
OO.87 Říká se možnostem metod atributy? Říká se jim možnosti, ale též atributy. Například tearoff = False v tk.Menu(tearoff=False), nebo master = okno jsou možnosti. Vlevo je název možnosti (tearoff, master) vpravo její hodnota (False, okno).
OO.88 Co dělá a jak funguje add_cascade()? Funguje stejně jako okno.configure(menu = korenove_menu) (O.84) jen s tím rozdílem, že se používá na Záložkách nižšího řádu. Tzn. nejde použít na kořenové záložce. Tedy přiřazuje určitou Záložku do kaskády pod kořenovou záložku: korenova_zalozka.add_cascade(label = "něco", menu = podzalozka). Zároveň přiřazuje widgetu tk.Menu text možností label. Widget tk.Menu totiž nemá možnost přidání textku.
OO.89 Jaké druhé notací existují?
  • infixní - notační znak se vkládá mezi prvky (např. 3 +5, nebo "Hello, " + "World!")
  • prefixní (polská) - notační znak se vkládá před prvky (print("Hello, World!"))
  • postfixní (obrácená polská) - notační znak se vkládá za prvky (3 5 +)
  • indexová - přístup k prvkům v seznamu, nebo řetězci (neco[0], neco[2]]
  • slovníková - umožňuje přístup k částem slovníku (slovnik['klic'])
  • lambda (lambda x: x * 2)
OO.90 Co řeší možnost weight při použití grafického manageru grid()? Řeší kolik zabere daný sloupec/řádka prostoru v defaultním stavu a při zvětšení. Pokud má například sloupec A váhu 1 a sloupec B váhu 2, bude mít sloupec B 2x větší šířku než sloupec A. Při zvětšování hlavního okna se pak bude tento poměr dodržovat. Pokud by měl sloupec B váhu 10, byl by 10x širší než sloupec A.
OO.91 Mají pack() a grid() nějakou možnost pro border? Závisí spíše na widgetu a není to tak robustní, jako v případě CSS. Možná by šlo nasimulovat, tzn. udělat si simulační widget, který by v případě pack() možnostmi expand = True, a fill = "both" a v případě grid() a možnosti sticky = "nsew" vyplnil celý prostor a následně použít velky pady a padx, které by vytvořili pouze rám. Jenomže v pack() rozvržení se mi nemůžou widgety překrývat, tak pak tam nemohu vložit další pracovní.
OO.92 Co je to notace? Notace jsou metainformace, které svými znaky a systémem zvýrazňují syntax a sémantiku.
OO.93 Lze zařídit, aby mi při přidělení vah v grafickém manageru grid() nemizely prvky při zmenšování hlavního okna? Nepřímým způsobem je nastavení metody minsize(). Pokud má okno výchozí rozměry (okno.geometry("600x400")), je možné nastavit minimální velikost na stejný rozměr (okno.minsize(600, 400)).
OO.94 Proč mi funguje skript i když tam mám překlepy? Například import tkinter as tik, ale níže volám hlavní okno jako tk.Tk(). Pravděpodobně proto, že používám REPL a již jsem ve stejné seanci dříve nahrál tkinter do jmenného prostoru tk. Takže v novém importu provedu jen nový import do tik a tudíž mě bude fungovat jak volání tk.Tk(), tak tik.Tk(). Pokud se něco chová nestandardně, je dobré konzoli promazat, nebo restartovat.
OO.95 Od čeho se odvozuje relativní šířka widgetu?
OO.96 Má absolutní pozicování geometrického manageru place() atribut anchor? Má, anchor lze využít jak v relativním, tak v absolutním pozicování.
OO.97 Existuje obrácený atribut k aboveThis? Ano, belowThis.
OO.98 Co je to flag variable a jak se chová? Je to proměná s hodnotou Boolean, která označuje nějaký stav, ale není na něj přímo navázána.
OO.99 Existuje nějaké doporučení jaký geometrický manager použít na co? Není, ale pro jednoduší rozvržení se doporučují manager pack() a grid().
OO.100 Když je u place() jedna ze souřadnic zadána relativně a druhá absolutně, jedná se o relativní, nebo absolutní pozicování? Absolutní.
OO.101 Co dělá atribut uniform?
OO.102 Vykreslují se widgety na každém operačním systému jinak? Ano, tkinter se snaží reprezentovat výchozí nastavení GUI každého operačního systému, aby to lépe fungovalo.
OO.103 Jak odsadím widget zleva v grafickém manageru grid() (Debian)? Závisí na celkovém designu, ale jde třeba přidat do sticky east (sticky = "e"), to ho přisadí doprava a teoreticky odsadí zleva.
OO.104 Co je to třída a jak vypadá? Třída je něco jako šablona obsahující určitou část základních nastavení, které se dají následně natahovat do jiných objektů jako základ. Vytvářejí se tam, kde se něco repetitivně opakuje, aby se nemusel kód opakovat.
OO.105 Co dělá funkce super()?
OO.106 Proč musí funkce sama sebe spouštět přes __init__()?
OO.107 Jak funguje create_rectangle()? Vytváří čtverec, kdy se do závorky zadají pozice horního levého a poté dolního pravého roku pozice.
OO.108 Jaké má opoctatnění syntaxe znacka["text"] = vstupni_text namísto znacka.configure(text = vstupni_text)? Jde o to, že se běžně tímto způsobem volají hodnoty názvů ve slovníku.
my_dict = {'key1': 'value1', 'key2': 'value2'}
print(my_dict['key1'])
vypíše value1. Mohlo by to být i hodnota = my_dict["key1"].
OO.109 Odkud tk.StringVar() či tk.IntVar() získávají hodnoty, pokud neobsahují žádné parametry? Získávají je z objektu, který má v hodnotě vlastnosti textvariable (případně u některých widgetů variable) stejný řetězec jako je název proměné těchto metod. Pokud např. máme:
...
retezec_tlacitka = tk.StringVar()
tlacitko = ttk.Button( text = "Prostě tlačítko", textvariable = retezec_tlacitka)
...
Získává metoda StringVar() hodnotu v podobě řetězce z widgetu nebo proměnné tlacitko, protože je na ni napojena pomocí vlastnosti textvariable.
OO.110 Které widgety mají vlastnost textvariable a které naopak používají vlastnost variable? textvariable:
  • tk.Entry()
  • ttk.Button()
  • ttk.Combobox()

variable:

  • tk.Checkbutton() also ttk.Checkbutton()
  • tk.Radiobutton() also ttk.Radiobutton()
  • tk.Scale() also ttk.Scale()
  • tk.Spinbox() also ttk.Spinbox()
  • tk.Canvas()
  • tk.Listbox()
  • tk.Menu()
OO.111 Proč neposílá StringVar() na ttk.Radiobutton žádné hodnoty? Kód je následující:
...
radio_var = tk.StringVar()

radio_1 = ttk.Radiobutton(okno, text = "Kulatý knoflík 1", variable = radio_var, value = "radio 1").pack() 
radio_2 = ttk.Radiobutton(okno, text = "Kulatý knoflík 2", variable = radio_var, value = 2).pack()
...
OO.112 Má metoda columnconfigure() a rowconfigure() možnost řazení z jiného směru? Default je zleva a zeshora. Nemá, musela by se každá buňka obalit rámem metody pack a vysadit jinak. Pak by ale pozbývalo smyslu používat grid metodu a kód by byl moc složitý.
OO.113 Jaký je rozdíl mezi absolutním a relativním pozicováním? Rozdíl se projeví při změnách okna (pro widgety master), kdy při absolutním pozicování stojí widget stále na stejném místě, tzn. že se může schovat za hranu rámu okna, kdežto při relativním pozicování se mění a zůstává stále viditelný.
OO.114 Jakých hodnot může nabývat vlastnost fill? Závisí v jakém kontextu se používá. Většinou definuje barvu (u metod, které vytvářejí tvar - např. create_line()). Hodnoty jsou barvy anglicky v uvozovkách, tedy např. "red", "blue", "green", atd. Nicméně v případě geometrického manageru pack() definuje směr kterým se danný widget rozšíří (hodnoty x, y, both, none - none je výchozí hodnotou).
OO.115 Pokud je yview metoda, proč se za ní v zápise ttk.Scrollbar(okno, orient = "vertical", command = platno.yview) nepíš závorka?
OO.116 Co je to set v tkinter.configure(yscrollcommand = scrollbar.set)?
OO.117 Jak funguje metoda bind()? Propojuje určitý typ události s funkcí. Obecný zápis je widget.bind(udalost, funkce). Předdefinované typy událostí jsou řetězce, takže jsou v uvozovkách a jsou zvýrazněné špičatými závorkami (např. "<Button-1>"). Většinou tedy snímají události z klávesnice, myši, ale mohou přijímat i určitý typ virtuálních událostí. Tyto události se mohou na různých operačních systémech lišit (například Linux systémy nemají událost <MouseWheel>, která zaznamenává obecně skrolování myší (na Windows nahoru i dolu). Místo toho rozeznává dvě události<Button-4> pro scrollování nahoru a <Button-5> pro scrollování dolů.
OO.118 Jak funguje metoda yview_scroll()? Metoda definuje jakým způsobem se bude scrollovat, jestli po řádcích (atribut units), nebo po stránkách (pages). Prvním atributem je číslo, které určí o kolik takových řádků nebo stránek má widget poskočit. Nejčastěji se tak metoda váže na wedget Canvas, ale může se Vázat i na Text, nebo Listbox.
OO.119 Co je to event.delta? Delta je hodnota která udává o kolik se posune objekt, při jednom otočení kolečka myši. Zároveň určuje i směr pozitivní, nebo negativné hodnotou. Tato hodnota se získává z yview_scroll() při skrolování. Jinak řečeno lambda funkcí přiřadíme k lokální proměnné event blok hodnot

(<MouseWheel event send_event=true delta=120 x=482 y=281>) a následně voláme sekci delta přes event.delta. Toto ale funguje jen ve spojení s událostí <MouseWheel>. Na Linuxu a v systémech s X11 tato možnost chybí a alternativní události <Button-4> a <Button-5> tuto informaci negenerují (viz <ButtonPress event state=Mod2 num=4 x=340 y=156>).

Tím že ve Windows funguje událost <MouseWheel> a v Linuxu ne, řešíme scrollování v Tkinteru jinak pro oba systémy. Ve Windows by byl výsek kódu následující:
platno.bind("<MouseWheel>", lambda event: platno.yview_scroll(int(event.delta / 60), "units"))
Jelikož metoda .yview_scroll() umožňuje skrolovat a definuje způsob, získáváme z hodnoty události <MouseWheel> hodnotu sekce delta. Ta může být totiž jak plusová tak minusová, což nám zajistí, že se widget bude pohybovat nahoru a dolu a nemusíme kvůli tomu zřizovat další řádek kódu. Získanou hodnotu musíme převést na číslo a vydělíme ji například 60, čímž získáme 2 nebo -2. Plátno se tak v tomto případě posune o dvě řádky ("units") dolu, nebo nahoru (-2). Navíc byť na MacOs funguje stejná událost jako na Windows, je jiná hodnota a tudíž musíme použít jiné dělení (tedy nelze dělit 60). V Linuxu se tento problém řeší dvoumi řádky kódu:
platno.bind("<Button-5>", lambda event: platno.yview_scroll(1, "units"))
platno.bind("<Button-4>", lambda event: platno.yview_scroll(-1, "units"))
OO.120 Lze přilepit událost ke kombinaci tlačítek na myši? Lze, pokud chci například posunout plátno doprava, mohu operátorem + spojit dvě události do jedné. Následující kód posune plátno o jedno doprava, pokud bude stisknuto levé a pak pravé tlačítko:
platno.bind("<Button-1>"+"<Button-3>", lambda event: platno.xview_scroll(1, "units"))
Pokud bych chtěl vyvolat akci tak, že jedno tlačítko držím a na druhé klikám, pak by bylo potřeba použít vlajkové proměnné a definovat vlastní funkce tak, jak je to uvedeno v následujícím příkladu:
left_button_pressed = False

def left_button_press(event):
    global left_button_pressed
    left_button_pressed = True

def left_button_release(event):
    global left_button_pressed
    left_button_pressed = False

def right_button_release(event):
    if left_button_pressed:
        print("Right mouse button released while left button was pressed")
        # Add your action here

root = tk.Tk()
frame = ttk.Frame(root, width=300, height=200)
frame.pack()

# Bind left button press and release events
frame.bind("<ButtonPress-1>", left_button_press)
frame.bind("<ButtonRelease-1>", left_button_release)

# Bind right button release event
frame.bind("<ButtonRelease-3>", right_button_release)

root.mainloop()
OO.121 Jak zjistím názvy jednotlivých událostí pro tlačítka myši? Například tak, že si nejprve ručně otestuji, jaké čísla mají jednotlivá kliknutí.
button = ttk.Button(window, text = "Test your mouse in here. Check event name in stdout.")
button.pack(expand = True, fill = "both", padx = 10, pady = 10)
button.bind("<Button>", lambda event: print(event.num))
A následně například na řádku 3 měním obsah názvu události těchto čísel a sleduji, jestli to na ten název reaguje (např. button.bind("<Button-1>", lambda event: print("povedlo se")) či button.bind("<Button-9>", lambda event: print("povedlo se"))).
OO.122 Co je to keysym a keycode? Keysym je symbol stisknuté klávesy a keycode její kód.
OO.123 Co znamená zápis: <ButtonPress event state=Control|Mod2 num=5 x=310 y=216>? Znamená, že byl stisknut Control (ButtonPressevent state=Control), byl zapnut numlock (Mod2), bylo scrollováno kolečkem myši k sobě (num=5) - pouze Linux, a pozice kurzoru na daném widgetu byla na ve vzdálenosti 310 pixelů od nuly na ose x a 216 na ose y.

Podobně tak <ButtonPress event state=Mod2 num=1 x=429 y=257> značí, že na pozici 429, 257 bylo při zapnutém numlocku stisknuto tlačítko 1, respetive Pravý kurzor myši.

OO.124 Jaká jsou čísla pro jednotlivá tlačítka myši a jakým názvům událostí to odpovídá?
  • levé tlačítko --> <Button-1> --> num=1
  • kliknutí na kolečko --> <Button-2> --> num=2
  • pravé tlačítko --> <Button-3> --> num=3
  • točení kolečkem od sebe --> <Button-4> --> num=4
  • točení kolečkem k sobě --> <Button-5> --> num=5
Zjištěno dle O.122
OO.125 Jaké jsou parametry metody insert()? Pro každý widget se používají jiné parametry. Pro widgety Entry a Text se jedná o index a text. Index značí kam se má text vložit, a text je samotný text pro vložení.

Hodnotou parametru index je buď číslo (integer), nebo text. Text může být ve formátu "řádek.znak" (např. "1.0") či konkrétní řetězec ("end", "insert", "current", "marks"). To, kterou formu zvolit závisí i na widgetu.

Hodnota pozice uvedená jedním číslem se dá použít pouze u jednořádkových widtegů jako je Label, Entry, Button, Spinbox etc. Hodnota ve formátu "řádek.znak" pak u víceřádkových jako je Text a Scrolledtext. Konkrétní hodnoty se pak používají nejčastěji s widgetem Text.

Ukázka využití čísla pro vložení konkrétního řetězce na pozici 0 u widgetu Entry:

#Po kliknutí na tlačítko, se před číslo vloží mezinárodní předvolba 00420
def insert_number():
    num = 00420  
    entry.insert(0, str(num)) 

# Create the main window
root = tk.Tk()
root.title("Vložení mezinárodní předvolby")

# Create an Entry widget
entry = tk.Entry(root)
entry.pack()

# Create a Button to trigger the insertion
button = tk.Button(root, text="Insert Number", command=insert_number)
button.pack()
Ukázka vložení hodnotou "řádek.znak" u widgetu Text:
...
text = tk.Text(okno)
#Zde se vloží textový řetězec
text.insert("1.0", f"Toto je test")
#Do výše uvedeného textového řetězce se u pátého znaku vloží TEST
text.insert("1.5", "TEST")
text.pack(expand=True, fill = "both")
...
Ukázka vložení kontétního řeztězce (end) u widgetu Text:
...
text = tk.Text(okno)
#Zde se vloží textový řetězec
text.insert("1.0", f"Toto je test")
#Na konec řádku vloží řetězec TEST
text.insert("end", " TEST")
text.pack(expand=True, fill = "both")
...
Indexy typu "řádek.znak" se uplatní i při vyjímání s využitím metody get(). Zde se dá těmito indexy zadat i rozsah:
...
text = tk.Text(okno)
text.insert("1.0", f"Toto je test")
text.pack(expand=True, fill = "both")

#Vyjme slovo "je"
text_content = text.get('1.4','1.7')
print(text_content)
...
OO.126 Jaké parametry má widget Treeview? Obecný zápis je ttk.Treeview(kontajner, možnosti), tedy ttk.Treeview(master = kontajner, moznost1 = hodnota, moznost2 = hodnota). Master je asi povinný. Možnosti jsou:
  • columns - obsahuje názvy sloupců v ntici, nebo proměné. Nejedná se ale o názvy, které se zobrazí ve widgetu. Ty se musí ještě definovat pomocí metody heading(). Pokud tedy udám, že hodnotou columns je "sloupec 1", musím pak ještě zapsat .heading("sloupec 1", text="Hrušky") což mi definuje, že sloupec se bude jmenovat Hrušky.
  • show - definuje viditelnost nultého sloupce a nadpisu:
    • show = "" - nezobrazí nultý sloupec ani nadpis
    • show = "heading" - nezobrazí nultý sloupec
    • show = "tree" - nezobrazí nadpis
    • show = "tree headings" - zobrazí oboje (default)
OO.127 Lze u metody insert() zapsat parametry i se jmény? Ano, lze. Je možný zápis s pojmenovanými parametry (.insert(index = 0, text = "00420")) i bez nich (.insert(0, "00420")).
OO.128 Co znamená následující zápis: table.insert(parent = "", index = tk.END, values = (choice(jmena), choice(prijmeni)))? Metoda insert() vkládá nějaké hodnoty do widgetu Treeview. parent = "" znamená, že hodnoty se budou vkládat hned za kořenový sloupec. index = tk.END znamená, že každá nová řádka bude vložena na konec. Nakonec parameter values vkládá hodnoty do řádků. V něm je metoda choice() z knihovny random, která vybírá hodnoty nahodile z proměnných jmena a prijmeni. Tím, že jsou obě metody uzavřeny v klasických závorkách jedná se o ntici, která sytí dva sloupce.
OO.129 Jak zjistím jakou mám Tkinter verzi?
from tkinter import TkVersion

print(TkVersion)
OO.130 Jak rozumět tomuto kódu: platno.create_window((20,50), window = ttk.Button(okno, text = "Značka"))? Metoda create_window() vytváří ve widgetu Canvas okno, které umožňuje vkládat další widgety. Následujou koordináty umístění středu okna x a y, tedy 20 a 50. Parametr window, za který se dá vložit jeden libovolný widget v tomto případě ttk.Button, do jehož závorky se samozřejmě vloží jeho parametry.
OO.131 create_window() parameter background? Nemá.
OO.132 Jaký je princip převodu kódu na třídu?
OO.133 Jak poznám, které atributy má konkrétní metoda? Například na webu https://www.pythontutorial.net/tkinter. Nebo v komentářích některých py souborů (např. v /usr/lib/python3.11/tkinter/__init__.py)
OO.134 Jak funguje metoda call()? Umožňuje spouštět Tcl příkazy z Pythonu.
OO.135 Které widgety mají atribut command?
  • button
  • checkbutton
  • radiobutton
  • menu
OO.136 Co dělá atribut menu (metody configure())? Přidává widget ttk.Menu do widgetu tk.Tk().
OO.137 Jak funguje možnost anchor u geometrického manageru place()? Je to bod kolem kterého se otáčí danný widget, tak že pozice mezi tímto bodem a levým horním okrajem parent okna musí sedět.

Defaultní je pozice v levém horním rohu, tedy anchor = "nw" (což je z anglického north west). Dají se ale definovat všechny základní pozice jako "n", "ne", "e", "se", atd. včetně pozice "center". Neznamená to, ale že by se pozice počítala od tohoto bodu. Ať už používáme absolutní pozicování v pixelech či relativní v procentech (respetive v číslech od 0 do 1), tak se to vždy vypočítává od levého horního okraje okna či otcovského widgetu.

Následující kód a komentáře v kódu celý koncept vysvětluji:
#(Z knihovny tkinter) naimportuj modul tkinter a vlož ho do jmenného prostoru tk
import tkinter as tk
#Z knihovny tkinter naimportuj modul ttk (a vlož ho do jmenného prostoru ttk)
from tkinter import ttk
  
#Základní okno
okno = tk.Tk()
okno.title("Anchor")
okno.geometry("300x400")
okno.minsize(300, 400) #Definuje velikost okna pod kterou ho nejde zmenšit

znacka_1 = ttk.Label(okno, text = "widget 1", background = "orange")
znacka_2 = ttk.Label(okno, text = "widget 2", background = "pink")
znacka_3 = ttk.Label(okno, text = "widget 3", background = "aqua")

#Všechny níže uvedené widgety jsou umístěné 100 px od osy x a 200 px od osy y, respetive od levého horního rohu
#Rozdíl je jen v tom, ke kterému bodu widgetu to je vzdálenost:
znacka_1.place(x = 100, y = 200, width = 100, height = 50)#K levému hornímu
znacka_2.place(x = 100, y = 200, height = 100, anchor = "se")#K pravému dolnímu
znacka_3.place(x = 100, y = 200, anchor = "center")#Do centra
  
#Spuštění okna a čekání na události
okno.mainloop()
Výsledek by vypadal následovně:
OO.138 Které přednastavené názvy barev existují? Je jich hodně, viz tento odkaz.
OO.139 Jak zjistím, jestli mám staženou určitou komponentu? Např.
import customtkinter#název modulu
print("")
OO.140 Jak nainstalovat v bashi customtkinter? pip install customtkinter
OO.141 Je customtkinter vhodný pro Linux? Zdá se že ne. Zdá, se že vývojář řeší pouze Windows a MacOS.
OO.142 Je customtkinter knihovna, nebo modul? Knihovna
OO.143 Proč jsou zaoblené rohy customtkinter na Linux tak hnusné? Vývojář to zřejmě neřeší.
OO.144 Co je to ttkbootstrap? knihovna
OO.145 Jaké themes existují v ttkbootstrap? litera, minty, lumen, sandstone, yeti, pulse, united, morph, journal, darkly
OO.146 Co zajišťuje metoda PhotoImage()? tk.PhotoImage(file=cesta k souboru) vytváří z obrázku objekt obrázku (<class 'tkinter.PhotoImage'>), který je pak možné přes atribut image vložit do některých widgetů. Do widgetu tedy není možné rovnou vložit cestu k souboru, ale musí se vytvořit objekt obrázku, který se sem vloží:
...
img = tk.PhotoImage(file = IMG_2154.JPG)

tlacitko = ttk.Button(okno, text = "Tlačítko", image = img)
tlacitko.pack()
....
OO.147 Jak REPL pozná, kterou metodu využít, pokud natahuju více knihoven, které mají stejné názvy knihoven? Nepozná, používá metody posledního importu, tedy toho co je nahoře nejníž.
OO.148 Je běžné při natahování více knihoven uvádět u všech metod jmenný prostor? Ano, jinak by mohlo dojít k problému.
OO.149 Co je event.width a co to umí? width je atribut z objektu vloženého do proměnné event. Tyto atributy jsou často svázány s událostmi metody bind(). Daný objekt může vypadat následovně:
<Configure event x=143 y=0 width=457 height=400>
Z výše uvedeného objektu můžeme vyčíst, že se jedná o událost "<Configure>", tedy událost, která často reaguje na změny polohy a velikosti určitého widgetu. Tato událost pak obsahuje čtyři atributy s hodnotami. width označuje šířku widgetu v určitém specifickovaném čase. Pokud chci tuto hodnotu následně přiřadit k nějaké proměnné, mohu ji vytěžit následujícím způsobem:
moje_promena_sirky = event.width
a dále s ní pracovat.
Pro zobrazení objektu dané události, lze použít následující zobecněný kód: widget.bind("<udalost>", lambda objekt: print(objekt)). Konkrétně by to tedy mohlo vypadat takto:
import tkinter as tk
...
okno = tk.Tk()
okno.geometry("600x400")
...
canvas = tk.Canvas(okno, background = "green", bd = 0, highlightthickness = 0, relief = "ridge")
canvas.grid(column = 1, columnspan = 3, row = 0, sticky = "nsew")
canvas.bind("<Configure>", lambda event: print(event))
a výsledek by byl například <Configure event x=143 y=0 width=457 height=400>.
OO.150 Co dělá canvas.create_image()? Přidá obrázek do widgetu Canvas.
OO.151 Widgety se při změnách velikosti okna pomalu překreslují, takže je vidět po stranách barevný podklad. Jak se toho zbait?
OO.152 Má metoda canvas.create_image() možnost anchor = "center"?
OO.153 Jaké jsou atributy metody canvas.create_image()?
OO.154 Co dělá metoda canvas.create_window()? Vytváří widget window, který do sebe umožňuje vkládat další widgety a tím se mohou dostat různé widgety na Canvas.
OO.155 Jak funguje atribut window, metody canvas.create_window()?
OO.156 Jak se liší argumenty self a parent, kdy je self hodnotou master a kdy argumentem?
OO.157 Co je to atribut parent a kde se používá? Parent ve třídě je zástupným parametrem pro hodnotu odesílanou z globálu. Hodnotou může být okno, tedy hlavní okno, ale i rám.
OO.158 Jaký je rozdíl mezi použitím podtržítka (_) v loopu a dvojitéhopodtržítka (__)?
OO.159 Co to je rekurze? Technika, kdy funkce volá sebe sama, aby získala výsledek.
OO.160 Jakým způsobem fungují poziční argumenty u tříd?
OO.161 Jak se zobrazí zdrojový kód ttk.Frame? Nejprve je potřeba si uvědomit, že i samotný ttk.Frame může dědit kód od nadřazených tříd. K tomu bysme ostatně došli, kdybysme si vypsali jeho kód. Strom dědičností je následující:

Pro vytištění kódu ttk.Frame můžeme použít následný kód:
import inspect
from tkinter import ttk

zdrojovy_kod = inspect.getsource(ttk.Frame)

print(zdrojovy_kod)
Pokud bysme chtěli všechny zdrojáky v řadě, může to vypsat do stdout, nebo do souboru, který si hned otevřeme:
import inspect
import tkinter
from tkinter import ttk
import subprocess

#Získá kódy jednotlivých tříd
zdrojovy_kod_1 = inspect.getsource(ttk.Frame)
zdrojovy_kod_2 = inspect.getsource(ttk.Widget)
zdrojovy_kod_3 = inspect.getsource(tkinter.Widget)
zdrojovy_kod_4 = inspect.getsource(tkinter.BaseWidget)
zdrojovy_kod_5 = inspect.getsource(tkinter.Misc)
zdrojovy_kod_6 = inspect.getsource(tkinter.Pack)
zdrojovy_kod_7 = inspect.getsource(tkinter.Place)
zdrojovy_kod_8 = inspect.getsource(tkinter.Grid)

#Vytiskne ttk.Frame až tkinter.Misc do konzole
#print(f"{zdrojovy_kod_5}\n {zdrojovy_kod_4}\n {zdrojovy_kod_3}\n {zdrojovy_kod_2}\n {zdrojovy_kod_1}")

#Vytiskne rovnocené rodičovské třídy ke třídě tkinter.Widget do stdout
#print(f"{zdrojovy_kod_8}\n {zdrojovy_kod_7}\n {zdrojovy_kod_6}")


#Vytvoří dva txt soubory s kódem tříd uspořádaných za sebou
with open('ttkFrame_to_tkMisc.txt', 'w') as file:
    file.write(f"{zdrojovy_kod_5}\n {zdrojovy_kod_4}\n {zdrojovy_kod_3}\n {zdrojovy_kod_2}\n {zdrojovy_kod_1}")

with open('tkWidget_parent_classes.txt', 'w') as file:
    file.write(f"{zdrojovy_kod_8}\n {zdrojovy_kod_7}\n {zdrojovy_kod_6}")

#A tyto dva soubory pak mohu rovnou otevřít
subprocess.run(['open', 'ttkFrame_to_tkMisc.txt'])
subprocess.run(['open', 'tkWidget_parent_classes.txt'])
OO.162 Jak se vloží proklikávatelná ikona, tj. obrázek?
OO.163 Může mít tlačítko na pozadí obrázek?
OO.164 Co umí a dělá filedialog?
OO.165 ttk.spinbox metodu get()? Ano.
OO.166 Proč atribut underline z ttk.Label má jednou hodnotu číslo a podruhé bool?
OO.167 Které widgety mohou mít vertikální orientaci?
  • tk.Scale, ttk.Scale
  • tk.Scrollbar, ttk.Scrollbar
  • ttk.Progressbar
  • ttk.Separator
  • ttk.Notebook
  • tk.PanedWindow, ttk.PanedWindow
Nicméně například i tlačítko lze přinutit k vertikálnosti a to prostřednictví geometrického manageru grid a zadání přesahu přes několik řádek. Například: checker_button.grid(column = 0, row = 0, rowspan = 6, sticky = "nsew").
OO.168
OO.169

Chyby a řešení

[editovat]

Při zapisování chybových hlášení je dobré zapsat i část kódu, která chybu způsobuje.

Č. Kód Chyba Odstraňování chyby Vysvětlení Poznámky
CHŘ.1
import tkinter as tk

#Výchozí okno
okno = tk.Tk()
okno.title("Prostě vokno")
okno.geometry("500x500")

#Widgety
promena_text = tk.Text(master = window)
promena_text.pack()

#Spouštěcí code
okno.mainloop()
  File "<string>", line 1, in <module>
NameError: name 'promena_text' is not defined
ChatGPT odhalili, že volám neexistující master. Hodnota nemá být window, ale okno.
CHŘ.2
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "<string>", line 2, in read_and_insert_default
AttributeError: 'Label' object has no attribute 'get'
Widget Label nemá metodu get(), která byla v kodu použitá na druhém řádku ve funkci "read_and_insert_default".
CHŘ.3
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "<string>", line 4, in insert_default
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1686, in __setitem__
    self.configure({key: value})
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1675, in configure
    return self._configure('configure', cnf, kw)
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1665, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: unknown option "-pady"
Používat vlastnost padding. Vypadá to jakoby metoda configure() na widgetu Label neměla možnst "pady", nicméně na diskusní stránce Pythonu mi řekli, že možnosti configure() jsou totožené s možnostmi widgetu. O.10
CHŘ.4
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "<string>", line 5, in insert_default
NameError: name 'yellow' is not defined
Protože hodnotu konfigurační možnosti mám zadávat jako řetězec, tedy v uvozovkách. Jinak je to chápáno jako proměnná. Tedy   znacka["background"] = "yellow", ne   znacka["background"] = yellow.
CHŘ.5
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "<string>", line 2, in uncheck_checkbutton_and_print_its_value
AttributeError: 'str' object has no attribute 'set'
CHŘ.6
...
okno.bind("<KeyPress>", lambda: print("Něco bylo stisknuto"))
...
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
TypeError: <lambda>() takes 0 positional arguments but 1 was given
...
okno.bind("<KeyPress>", lambda event: print("Něco bylo stisknuto"))
...
Tím, že metoda widget.bind() posílá do lambdy nějaká data, je potřeba je poslat do proměnné event. Kdybych do lambdy žádná data neposílal, proměnou nepotřebuji. Např.: tlacitko3 = ttk.Button(master = okno, text = "Pokusne tlacitko", command = lambda: print("čau")).pack() Zde je lambda navázána na atribut command a nejsou do ni posílána žádná data.
CHŘ.7
...
text.bind("<FocusIn>"+"<Shift>"+"<MouseWheel>", lambda vybrano: print("Mousewheel"))
...
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1421, in bind
    return self._bind(('bind', self._w), sequence, func, add)
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1375, in _bind
    self.tk.call(what + (sequence, cmd))
_tkinter.TclError: bad event type or keysym "Shift"
Protože v Tkinteru nelze spárovat výstupy různých eventů.
CHŘ.8
...
combo = ttk.Combobox(master = okno).pack()
combo["values"] = polozky
...
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: 'NoneType' object does not support item assignment
...
combo = ttk.Combobox(master = okno)
combo.pack()
combo["values"] = polozky
...
Jde o to, že se do proměnné zapisuje poslední část řetězce, tedy v tomto případě pouze pack(), proto pack() musí být na separátním řádku mimo řetězec.
CHŘ.9
...
polozky = ("Zmrzka", "Pizza", "Mrkev")
combo = ttk.Combobox(master = okno)
combo["items"] = polozky
...
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1686, in __setitem__
    self.configure({key: value})
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1675, in configure
    return self._configure('configure', cnf, kw)
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1665, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: unknown option "-items"
...
polozky = ("Zmrzka", "Pizza", "Mrkev")
combo = ttk.Combobox(master = okno)
combo["values"] = polozky
...
Hodnoty v závorkách jsou pro ttk.Combobox předdefinovány, takže člověk musí vložit hodnotu values.
CHŘ.10
stredova_znacka = ttk.Label(okno, text = "Středová značka", background = "pink")
stredova_znacka.pack(x = 0, y = 0, width = 200, height = 200, anchor = "center")
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.10/tkinter/__init__.py", line 2425, in pack_configure
    self.tk.call(
_tkinter.TclError: bad option "-x": must be -after, -anchor, -before, -expand, -fill, -in, -ipadx, -ipady, -padx, -pady, or -side
stredova_znacka = ttk.Label(okno, text = "Středová značka", background = "pink")
stredova_znacka.place(x = 0, y = 0, width = 200, height = 200, anchor = "center")
Použit chybný geometrický manager. Má být place(), byl pack().
CHŘ.11 Zřejmě se to týká, tohoto kódu:
znacka3 = ttk.Label(okno, text = "Značka 3", background = "blue").place(
  x = 70, y = 110, width = 200, height = 150
)
tlacitko3 = ttk.Button(okno, text = "Tlačítko 3", command = lambda: znacka3.lower()).place(
  rely = 1, relx = 0.6, anchor = "se"
)
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "<string>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'lower'
znacka3 = ttk.Label(okno, text = "Značka 3", background = "blue")
znacka3.place(  x = 70, y = 110, width = 200, height = 150)
ttk.Button(okno, text = "Tlačítko 3", command = lambda: znacka3.lower()).place(rely = 1, relx = 0.6, anchor = "se")
Šlo by to například řešit takto. Jde o to, že pokud geometrický manager place() posílá hodnotu do promené značka, nevysílá ve skutečnosti nic. Proto nelze v následujícím kroku provést na hodnotě NoneType metodu lower(). Když se ale geometrický manager posune na novou řádku a pouze se aplikuje na proměnou znacka3, tak to jde. Protože widget generuje proměnou konkrétního widgetu (<class 'tkinter.ttk.Label'>) a na tomto typu hodnoty lze provést jak umístění (prostřednictvím place()), tak aplikovat metodu lower().

Pokud dále nepracuju s tlačítkem 3, nepotřebuji vytvářet promenou tlacitko3. Pokud bych to potřeboval mohl bych obsah řádku 3 přiřadit promenné tlacitko3 a vše by fungovalo. Nicméně kdybych pak ten placeholder tlacitko3 chtěl volat, nebo na něm provádět nějakou operaci, musel bych se opět zbavit geometrického manageru, protože by hodnota této proměnné byla NoneType.

To jaký typ hodnoty mi daný kód generuje lze zjistit pomocí print(type(název proměnné)).

CHŘ.12
import tkinter as tk
from tkinter import ttk
...
img = tk.PhotoImage(file = "/home/juan/~/kabrinec4d.jpg")
...
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.10/tkinter/__init__.py", line 4103, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "/usr/lib/python3.10/tkinter/__init__.py", line 4048, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize data in image file "/home/juan/~/kabrinec4d.jpg"
import tkinter as tk
from tkinter import ttk
...
img = tk.PhotoImage(file = "/home/juan/~/kabrinec4d.pgm")
...
CHŘ.13
import tkinter as tk
from tkinter import ttk

class Segment(ttk.Frame):
	def __init__(self, parent, text_znacky, text_tlacitka):
		super().__init__(master = parent)

		#Vytvoření gridu
		self.rowconfigure(0, weight = 1)
		self.columnconfigure((0,1,2), weight = 1, uniform = "a")
		ttk.Label(self, text = text_znacky).grid(row = 0, column = 0, sticky = "nsew")
		ttk.Button(self, text = text_tlacitka).grid(row = 0, column = 1, sticky = "nsew")

		self.pack(expand = True, fill = "both", padx = 5, pady = 2)
	
		self.mensi_segment()
	
	def mensi_segment(self):
		kontys = ttk.Frame()
		kontys.grid(row = 0, column = 2)

		vstup = ttk.Entry(kontys, text = "Vstup").pack()
		tlacitko = ttk.Button(kontys, text = "Tlačítko 3").pack()
#Okno
okno = tk.Tk()
okno.title("Mnohočetný otisk jedné třídy")
okno.geometry("400x600")

#Widgety
Segment(okno, "Značka", "Tlačítko")
Segment(okno, "Značka 2", "Tlačítko 2")
Segment(okno, "Značka 3", "Tlačítko 3")
Segment(okno, "Značka 4", "Tlačítko 4")
Segment(okno, "haf", "haf")

#Spuštění okna a čekání na události
okno.mainloop()
Traceback (most recent call last):
  File "/home/juan/~/025 kombinace oop a funkcniho pristupu.py", line 43, in <module>
    Segment(okno, "Značka", "Tlačítko")
  File "/home/juan/~/025 kombinace oop a funkcniho pristupu.py", line 21, in __init__
    self.mensi_segment()
  File "/home/juan/~/025 kombinace oop a funkcniho pristupu.py", line 25, in mensi_segment
    kontys.grid(row = 0, column = 2)
  File "/usr/lib/python3.10/tkinter/__init__.py", line 2522, in grid_configure
    self.tk.call(
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack
CHŘ.14
CHŘ.15

Související otázky

[editovat]

Otázky, které se netýkají hlavního předmětu, ale souvisí s ním. Zvažte zapsání dotazu a odpovědi na stránku, která je tématu bližší (seznam dostupných témat).

Č. Otázka Detailní popis, fotografie, video Odpověď Poznánky
1 Jak se vypočte poměr stran určitého objektu? U objektů, které mají více stran, se poměr vztahuje vždy ke konkrétní straně. Obdélník, nebo obrázek o poměru 16:9 má jinou orientaci, než obdélník o poměru stran 9:16. Poměry u jednotlivých obrazců lze vyjádřit i následovně:
  • čtverec 1 (protože )
  • obdélní a:b (tedy )
  • trojůhelník strana2
  • kružnice 0,318
  • elipsa delší průměr:kratší průměr
2 Jaký je vrozreček pro zoom objektu?
3 Jak myslí matematiky? Představuje si nějaké objekty?
4 Je matematika jazyk?