app.py — úvodní obrazovka hry PyQueststreamlit, pillowTenhle blok je jen pro vás — dětem ho nepromítejte. Je to plán, podle kterého se řídíte.
| Fáze | Co se děje | Čas |
|---|---|---|
| Instalace | Všichni rozjedou Python a Streamlit | 20 min |
| První spuštění | streamlit run, hot-reload, okna vedle sebe |
15 min |
| Výklad + ukázky | Bloky 4–10, střídáte mluvení a promítání kódu | 45 min |
| Cvičení | Děti pracují samy, vy obcházíte | 55 min |
| Závěr | Kdo chce, ukáže svůj výsledek | 5 min |
Dnešní hodina nemá naučit programovat. Má vytvořit zážitek „změnil jsem číslo a obrazovka se změnila". Všechno ostatní (proměnné, podmínky, cykly) staví na tomhle pocitu moci nad obrazovkou. Pokud dítě odchází a chce doma pokračovat, hodina se povedla, i kdyby nerozumělo ani slovu ze slova „funkce".
Jak pracovat se smíšenou úrovní. Každé cvičení má tři stupně: Minimum, Rozšíření, Výzva. Slabším řekněte, že stačí Minimum a je to úspěch. Rychlíkům dejte hned Výzvu a pak je posaďte jako pomocníky k někomu, kdo se trápí. Vysvětlování je nejlepší způsob, jak se něco naučit — a vám to ušetří půl hodiny běhání.
Tohle je úplně první věc, kterou uděláte. Dokud nemá každý běžící Streamlit, nemá smysl začínat s výkladem. Napište příkazy na tabuli a obcházejte.
python --version
Ověření, že Python vůbec je. Musí vypsat něco jako Python 3.11.5.
Číslo musí být 3.9 nebo vyšší.
Když příkaz vypíše chybu nebo se otevře Microsoft Store, Python není nainstalovaný — stáhněte ho z python.org a při instalaci na Windows zaškrtněte „Add Python to PATH". Tohle políčko je nejčastější příčina toho, že pak nic nefunguje.
python3 --version
Na Macu a Linuxu je potřeba psát python3. Samotné python tam
buď neexistuje, nebo ukazuje na starou verzi 2.7.
Řekněte dětem rovnou: „Kdo má Mac, píše všude python3 místo python."
Ušetříte si tím deset stejných dotazů.
python -m pip install streamlit pillow
Instalace obou knihoven naráz. Trvá to jednu až tři minuty a vypíše to spoustu řádků — to je normální, děti se toho leknou.
Proč python -m pip a ne jen pip? Když má někdo v počítači víc Pythonů,
samotné pip může instalovat do toho špatného. Zápis python -m pip říká
„nainstaluj to do tohohle Pythonu, kterým to spouštím". Je to spolehlivější.
python -m pip install --user streamlit pillow
Záložní varianta, když instalace selže na právech. Na školních počítačích
běžné. Přepínač --user nainstaluje knihovny do domovské složky uživatele,
kde má právo zapisovat vždycky.
Když ani tohle nezabere, je na vině nejspíš antivirus nebo firewall školy.
streamlit hello
Kontrola, že to funguje. Otevře se prohlížeč s ukázkovou aplikací přímo od tvůrců Streamlitu.
Tohle je zároveň skvělý motivační moment: nechte děti minutu klikat na ukázky v levém menu (hlavně Plotting Demo a Mapping Demo) a řekněte: „Tohle všechno je napsané v Pythonu. Za dvě hodiny budete umět udělat něco podobného."
Zastavíte to v terminálu klávesami Ctrl+C.
.zip obsahujícím hotové soubory demo/, cviceni/ a reseni/.Tohle je největší motivační trik celé hodiny. Postup si předem vyzkoušejte, ať před dětmi neváháte.
streamlit run app.py
Takhle se spouští Streamlit aplikace — a jenom takhle.
V VS Code otevřete složku projektu (File → Open Folder), pak terminál
(Ctrl+` nebo Terminal → New Terminal) a napíšete tenhle příkaz.
Otevře se prohlížeč na adrese http://localhost:8501.
Zdůrazněte dětem: python app.py nefunguje. Vypíše to varování
nebo prázdno. Musí to být streamlit run.
VS Code Prohlížeč
┌──────────────┐ ┌──────────────┐
│ app.py │ │ PyQuest │
│ │ Ctrl+S│ │
│ st.title( │───────►│ ⚔️ PyQuest │
│ "PyQuest") │ │ │
│ │ │ │
└──────────────┘ └──────────────┘
Okna dejte vedle sebe. Tohle je klíčové.
Na Windows: Win + ← na VS Code, Win + → na prohlížeč.
Na Macu: přetáhněte okna nebo použijte Split View.
Dokud dítě přepíná mezi okny Alt+Tab, nevidí souvislost mezi kódem
a výsledkem. Jakmile je má vedle sebe, souvislost je okamžitá a samozřejmá.
Obejděte třídu a zkontrolujte, že to tak má opravdu každý.
Prohlížeč → ⋮ (vpravo nahoře)
→ Settings
→ ☑ Run on save
Zapnutí automatického překreslení.
Bez tohohle se po uložení souboru objeví vpravo nahoře jen tlačítko Rerun a hláška „Source file changed". Funguje to taky, ale dítě musí pokaždé kliknout.
Se zapnutým Run on save stačí Ctrl+S a stránka se překreslí sama.
Rozdíl v zážitku je obrovský.
Jak to předvést dramaticky.
Napište na projektoru tenhle kód. Uložte. Ukažte výsledek. Pak před zraky dětí
změňte text na "🔥 AHOJ SVĚTE 🔥" a znovu Ctrl+S.
Stránka se změní během sekundy. Tady většinou nastane ten moment, kdy si děti uvědomí, že mají nad obrazovkou moc.
Nechte je pak deset vteřin jenom přepisovat ten text. Vyplatí se to.
Server běží pořád, dokud ho nezastavíte Ctrl+C. Děti budou zavírat
křížkem prohlížeče a divit se, že to pořád běží. Nebo naopak spustí streamlit run
podruhé a dostanou hlášku Port 8501 is already in use.
Naučte je jednu větu: „Zavřít stránku nestačí. Server se vypíná v terminálu klávesami Ctrl+C."
Zapamatuj si:
Když napíšeš program v Pythonu, normálně se výsledek vypíše jen jako text do černého okna. To je nudné a nikdo jiný to nepoužije. Streamlit je nástroj, který vezme tvůj Python kód a udělá z něj webovou stránku. Pořád píšeš obyčejný Python, ale místo textu v okně vidíš tlačítka, posuvníky a barvy — v prohlížeči, přesně jako opravdové aplikace.
Jednoduchá představa:
Streamlit je kuchař. Ty mu dáš recept (soubor
app.py) a on podle něj uvaří stránku. Kdykoliv recept změníš, uvaří ji znovu.
app.py ──► Streamlit ──► webová stránka
(recept) (kuchař) (hotové jídlo)
Proč zrovna Streamlit a ne „opravdový" web?
Klasická webová stránka potřebuje tři jazyky najednou: HTML na obsah, CSS na vzhled a JavaScript na chování. To je pro dvanáctileté dítě příliš.
Streamlit tuhle bariéru odstraní. Píšeš jeden jazyk, jeden soubor, a přesto vidíš skutečnou webovou aplikaci v prohlížeči. Tu složitost si přidáme později a jenom po kouscích — kousek CSS uvidíš ještě dneska u barevných boxů.
import streamlit as st
Tenhle jediný řádek stojí za to pochopit pořádně.
Python sám o sobě neumí dělat webové stránky. Umí počítat, porovnávat a pracovat s textem — a to je všechno. Když chceš něco navíc, půjčíš si knihovnu: hotovou sadu nástrojů, kterou už napsal někdo jiný.
import streamlitznamená „přines mi bednu s nářadím na weby".as stznamená „a budu jí říkat zkráceněst, ať to nemusím psát pořád celé".
Od té chvíle každý příkaz začíná st. — a ta tečka znamená
„z týhle bedny mi podej tenhle nástroj".
import streamlit as st
from PIL import Image, ImageDraw
import random
Knihoven můžeš použít více a všechny se importují podobně.
streamlit — dělá webovou stránkuPIL (Pillow) — kreslí obrázky, použijeme na konci hodinyrandom — náhodná čísla, přijde v 11. hodiněRozdíl mezi import X a from X import Y si představ takhle:
import PILje „přines celou bednu".from PIL import Imageje „z bedny mi podej jenom kladivo, celou ji sem netahej".
Tohle ti dneska úplně stačí.
„Odkud se ty knihovny berou?" — Odpověď: ze stejného místa, odkud jsme je
před chvílí instalovali příkazem pip install. Je to obrovská online knihovna
hotového kódu, kterou zdarma sdílí programátoři z celého světa.
Jmenuje se PyPI a je v ní přes půl milionu knihoven.
Skupina 1 — příkazy, které ukazují.
Berou text a namalují ho na stránku. Nic nevracejí, nic se jich neptáte.
Nejdůležitější rozdíl, který se plete nejčastěji:
| Příkaz | K čemu |
|---|---|
st.title |
jen jednou nahoře, jméno aplikace |
st.header |
nadpis sekce |
st.write |
cokoliv — text, číslo, seznam |
st.markdown |
text s formátováním (**tučně**) |
st.write je „univerzální vypisovač" — zvládne i čísla a seznamy.
Když nevíš, co použít, sáhni po st.write.
Barevné zprávy a ukazatele.
Každý příkaz zobrazí jiný typ informace. Změň texty, čísla i hodnotu
delta a sleduj, jak se výsledek mění.
st.metric udělá „statistiku jako v aplikaci": velké číslo a pod ním
zelená nebo červená šipka se změnou. Parametr delta=25 znamená
„o 25 víc než minule", delta=-2 udělá červenou šipku dolů.
st.progress bere číslo od 0 do 1, ne od 0 do 100.
Tohle je klasický zdroj chyb: st.progress(70) spadne,
správně je st.progress(0.7).
Skupina 2 — příkazy, které se ptají.
Nakreslí ovládací prvek a vrátí zpátky hodnotu, kterou uživatel nastavil.
Proto je vždycky vidíte se znaménkem = a jménem vlevo.
Všimni si vzoru u všech: první parametr je popisek, další jsou nastavení:
st.slider("Úroveň", 1, 20, 3) → od 1 do 20, na začátku 3st.text_input("Jméno", "Arkon") → předvyplněné „Arkon"st.selectbox("Povolání", [...]) → seznam možností v hranatých závorkáchTen seznam v hranatých závorkách je mimochodem pole — přesně to, co se budeme učit v 6. hodině. Teď ho jen používáme.
Skupina 3 — příkazy, které rozdělují.
Nemalují nic viditelného, jen říkají, kam se má další obsah dát.
Zatím jsme psali všechno pod sebe jako nákupní seznam. Tyhle příkazy stránku rozdělí na police — a ty si vybereš, na kterou polici co položíš.
Zápis with neco: znamená „všechno, co je odteď odsazené, patří dovnitř".
Jakmile odsazení skončí, jsi zase venku.
Je to stejná logika jako u if — odsazení říká, co patří dovnitř.
V Pythonu odsazení určuje strukturu, ne jen vzhled.
Tyhle dva zápisy dělají totéž:
with st.sidebar:
st.header("Nastavení")
st.sidebar.header("Nastavení")
První bývá přehlednější, protože je hned vidět, kde blok začíná a končí.
Důležitá myšlenka: některé prvky na stránce vracejí hodnotu, se kterou můžeš dál pracovat.
Zkus, co se stane s hodnotou z okénka.
Tenhle jediný řádek dělá dvě věci najednou.
Zaprvé nakreslí na stránku okénko, do kterého se dá psát. Zadruhé vrátí zpátky to, co uživatel napsal — a my si to uložíme pod jméno
jmeno.Od té chvíle s tím můžeš dělat cokoliv.
Šipka směřuje zprava doleva: nejdřív se stane to napravo, a výsledek se uloží do jména nalevo. Tohle může být nezvyklé, protože normálně čteš zleva doprava.
Zkus s hodnotou z okénka něco udělat.
Zkus různá jména a sleduj, jak se mění všechny řádky pod okénkem.
Zatím neřeš, co přesně len() nebo .upper() dělají.
To jsou další nástroje a pořádně je probereme v sedmé hodině.
Teď sleduj hlavně to, že okénko něco vrátilo a my s tím počítáme.
Zápis [::-1] je trik na otočení textu.
Pořádně ho probereme, až budeme dělat řetězce.
U tlačítka je to trochu jinak — a je to důležité.
st.button()vrací ano/ne. Vrátí „ano" jenom v tu jedinou chvíli, kdy na něj někdo klikl. Jinak vrací „ne".Proto ho dáváme do
if— což se čte jako „jestliže".
Podmínkám se budeme pořádně věnovat ve 4. hodině. Dneska stačí, když pochopíš tenhle jeden vzor a umíš ho opsat:
if st.button("Text na tlačítku"):
(odsadit o 4 mezery)
co se má stát
Nejčastější chyba dneška: když zapomeneš odsadit řádek pod if,
text se ukazuje pořád. Pokud se ti to stane, zkontroluj,
že řádek pod if začíná čtyřmi mezerami.
Vyzkoušej tři úrovně barev — od nejjednoduššího zápisu až po barvu, která se mění podle hodnoty.
Úroveň 1 — vestavěné barvy. Začni tady.
Žádné HTML, žádné parametry navíc. Zápis je :barva[text].
Dostupné barvy: red, orange, green, blue, violet, gray, rainbow.
Každá má i variantu -background pro zvýraznění pozadí.
Tohle zvládne úplně každý a je to okamžitá odměna. Zkoušej chvíli různé kombinace barev a sleduj, co všechno jde.
Barvy fungují jenom v st.markdown() a st.write(), ne v st.title().
Když chceš barevný nadpis, použij st.markdown("# :red[Nadpis]") —
mřížka na začátku dělá velikost nadpisu.
Úroveň 2 — vlastní rámeček. Tady se dělá dojem.
style je seznam pravidel oddělených středníkem:
| Pravidlo | Co dělá |
|---|---|
background-color |
barva pozadí |
color |
barva písma |
padding: 20px |
mezera uvnitř rámečku |
border-radius: 12px |
kulaté rohy |
border: 3px solid gold |
rámeček |
text-align: center |
text na střed |
font-size: 28px |
velikost písma |
K čemu je unsafe_allow_html=True? Streamlit se normálně brání tomu,
aby se text bral jako HTML — je to bezpečnostní pojistka. Tímhle parametrem
mu říkáme „věř mi, tenhle text je opravdu HTML a chci ho tak zobrazit".
U školního projektu je to v pohodě, protože si HTML píšeš sám. Nebezpečné by to bylo hlavně tehdy, kdybys do něj vkládal cizí text z internetu.
#RRGGBB
└┬┘└┬┘└┬┘
│ │ └── modrá 00-FF
│ └───── zelená 00-FF
└──────── červená 00-FF
#FF0000 čistě červená
#00FF00 čistě zelená
#000000 černá
#FFFFFF bílá
#FFD166 zlatá
Jak přemýšlet o zápisu barvy.
Každá barva na obrazovce se míchá ze tří světel: červeného, zeleného a modrého. Zápis
#RRGGBBříká, kolik každého z nich přidat.Čísla jsou v šestnáctkové soustavě: jdou od
00(žádné světlo) poFF(naplno). Proto#FF0000je červená naplno a nic jiného, a#FFFFFFje všechno naplno, což dá bílou.
Nemusíš to chápat do hloubky. Stačí, když víš, že si barvu můžeš vybrat myší na htmlcolorcodes.com a zkopírovat ten kód s mřížkou.
Úroveň 3 — barva se počítá z dat.
Táhni posuvníkem pomalu dolů a sleduj, jak box mění barvu ze zelené přes oranžovou do červené.
Tady se poprvé sejde všechno dohromady:
slider vrátil číslo),if / elif / else vybral barvu),Tomuhle se říká, že aplikace reaguje na data. Přesně takhle fungují všechny hry a aplikace, které znáš.
f"""...""" znamená, že se do textu můžou vkládat hodnoty ve složených
závorkách. Dnes to jen používej. Pořádně to probereme
v 7. hodině u řetězců — teď stačí vědět, že f dovolí
vložit proměnnou do textu ve složených závorkách.
Sloupce — nejpoužívanější rozdělení.
Analogie:
Zatím jsme skládali věci pod sebe jako talíře na sebe.
st.columnsje police vedle sebe — vyberete si, do které přihrádky co položíte.
Řádek levy, pravy = st.columns(2) si přečti jako:
„Rozděl stránku na dvě části a tu první nazvi levy, tu druhou pravy."
Jména si volíš ty. Klidně a, b nebo hrdina, prisera — hlavně
ať jich je tolik, kolik je sloupců.
levy, pravy = st.columns(2)
# ├──────────┤├──────────┤ stejně široké
levy, pravy = st.columns([2, 1])
# ├───────────────┤├──────┤ levý dvakrát širší
a, b, c = st.columns([3, 1, 3])
# ├────────┤├──┤├────────┤ prostřední úzký
a, b, c, d = st.columns(4)
# ├─────┤├─────┤├─────┤├─────┤
Různé šířky — změň čísla a sleduj, co se stane.
Číslo v závorce = kolik sloupců. Seznam v hranatých závorkách = poměr šířek.
[3, 1, 3] neznamená pixely, ale poměr: první a třetí jsou třikrát širší
než prostřední. Když napíšeš [300, 100, 300], dopadne to úplně stejně —
protože jde jenom o poměr.
Poměr [2, 1, 2] je super na obrazovku souboje: vlevo hrdina,
uprostřed úzký sloupec s velkým VS, vpravo příšera.
Tenhle poměr se bude hodit ve cvičení 3.
Zbylá tři rozdělení — všechna fungují podobně.
| Příkaz | Vypadá jako | Kdy použít |
|---|---|---|
st.sidebar |
postranní lišta vlevo | nastavení, které nemá překážet |
st.tabs |
záložky jako v prohlížeči | víc obrazovek na jedné stránce |
st.expander |
rozbalovací šuplík | nápověda, detaily, řešení |
st.container(border=True) |
rámeček kolem skupiny | vizuálně oddělit část |
Sidebar je hodně atraktivní — hned to vypadá jako opravdová aplikace. Je to nejlepší místo pro všechna nastavení hry.
Všimni si, že všechny používají stejný vzor with ...: a odsazení.
Když jednou pochopíš tenhle vzor, umíš je všechny.
Souřadnice určují, kde se prvek objeví. Tuto myšlenku později použiješ v erbu i v herním poli projektu.
0 ─────────────────► X (doprava)
│
│ [0,0] je vlevo NAHOŘE
│
│ ● [150, 80]
│
▼
Y (DOLŮ!)
[50,50] ┌────────┐
│ │ rectangle([50, 50, 150, 100])
└────────┘ [150,100]
Tohle si představ přesně takhle.
V matematice roste Y nahoru. V počítačové grafice roste Y dolů. Je to proto, že obrazovka se odjakživa kreslila po řádcích shora dolů, jako když čtete knihu.
Zapamatuj si to, jinak ti bude všechno vzhůru nohama.
Zkus bez počítače určit: „Kde je bod [0,0]? A kde [200,0]? A [0,200]?" Jestli si tohle srovnáš v hlavě hned, ušetříš si spoustu zmatku.
Pět základních tvarů. Víc jich dneska nepotřebujeme.
Postup je vždycky stejný:
Image.new("RGB", (šířka, výška), "barva")ImageDraw.Draw(platno)stetec.neco(...)st.image(platno)Analogie, která funguje:
Je to jako malování na papír. Nejdřív si vezmeš papír, pak štětec, pak maluješ, a nakonec ho pověsíš na stěnu, aby ho ostatní viděli. Když zapomeneš na ten poslední krok, obrázek zůstane v šuplíku.
Zapomenutý st.image() je nejčastější chyba tohohle bloku.
Máš hotový obrázek, ale stránka je prázdná, protože jsi ho ještě neukázal.
# ŠPATNĚ - takhle to často svádí napsat
stetec.rectangle([50, 50, 100, 50])
# x y šířka výška ← NE!
# SPRÁVNĚ - zadávají se dva rohy
stetec.rectangle([50, 50, 150, 100])
# ├levý horní┤ ├pravý dolní┤
# výsledek: široký 100 px, vysoký 50 px
Tady se chybuje úplně nejčastěji.
Obdélník se nezadává jako „kde a jak velký". Zadávají se dva rohy: levý horní a pravý dolní.
[50, 50, 150, 100] znamená: „začni na [50,50] a skonči na [150,100]".
Ten obdélník je tedy 100 pixelů široký (150 − 50) a 50 vysoký (100 − 50).
Když chceš obdélník široký 100 od bodu [50,50], musíš napsat
[50, 50, 50+100, 50+50]. Klidně to tak napiš — Python to spočítá.
Kruh: Pillow nemá „nakresli kruh se středem a poloměrem".
Kreslí se elipsa vepsaná do obdélníku. Když je ten obdélník čtverec,
vyjde z toho kruh. Proto ellipse([300, 20, 370, 90]) dá kruh o průměru 70.
Vyvrcholení bloku: souřadnice přijdou z posuvníků.
Spusť ukázku a táhni posuvníky. Obrázek se překresluje okamžitě. Stejným principem se pohybují prvky ve hrách.
Všimni si té elegance: [x, y, x + velikost, y + velikost].
Levý horní roh je tam, kde je hrdina, a pravý dolní je o velikost
dál doprava a dolů. Změnou jednoho čísla se mění velikost i pozice zároveň.
Zkus si odpovědět: „Co se stane, když napíšu x - velikost místo
x + velikost?" Pak to rovnou vyzkoušej. (Odpověď: Pillow
si rohy prohodí nebo nenakreslí nic — a právě proto má pořadí rohů význam.)
Druhý způsob pozicování: emoji v HTML místo kreslení.
Stejná myšlenka souřadnic, ale místo Pillow se používá HTML. Má to tři výhody, kvůli kterým se ti to v projektu bude hodit:
linear-gradient udělá nebe a trávu jedním řádkem,Klíčová dvojice je position:absolute a left / top.
position:absoluteznamená „tenhle prvek si stoupne přesně tam, kam mu řeknu, a je mu jedno, co je kolem". Aleftstopříkají kam — zase v pixelech od levého horního rohu.
Vnější div musí mít position:relative, jinak se prvky umísťují
podle celé stránky místo podle herního pole. Ber to jako pravidlo,
bez kterého se to rozsype.
Tenhle blok dětem nepromítejte. Je to zázemí, díky kterému budete umět odpovědět na nečekané otázky.
Jak Streamlit doopravdy funguje. Spustí lokální webový server
(výchozí port 8501) postavený na Tornadu. Váš .py soubor není klasická
webová aplikace s routami — Streamlit ho spouští celý shora dolů
při každé interakci. Každé volání st.něco() přidá prvek do fronty
vykreslení, ta se serializuje přes Protobuf a pošle do prohlížeče
přes WebSocket, kde ji vykreslí React.
Skript se spustí odshora dolů. Pokaždé znovu. Kdykoliv uživatel na cokoliv klikne.
Tohle je nejdůležitější mentální model celého kurzu. Právě proto budete
v 5. hodině potřebovat session_state — jinak se všechno při každém
kliknutí vrátí do původního stavu. Dnes to ale dětem neříkejte.
Nechte je nejdřív zažít, že to funguje.
Analogie pro později: Streamlit je kuchař, který při každé změně objednávky nevaří dál od poloviny, ale zahodí talíř a uvaří celé jídlo znovu od začátku — jen s novou ingrediencí.
Proč to nevadí, že se to spouští pořád dokola? Protože naše skripty
jsou drobné a Python je zvládne za milisekundy. U velkých aplikací se to
řeší cachováním (@st.cache_data), ale to je daleko za obzorem tohohle kurzu.
Co se stane, když dvě děti otevřou stejnou adresu? Každý prohlížeč dostane vlastní session s vlastními hodnotami. Pokud budou chtít hrát spolu po síti, řekněte, že to jde, ale až po nasazení do cloudu — k tomu se dostaneme v 18. hodině.
Bezpečnost unsafe_allow_html. Riziko je jen tehdy, když do HTML
vložíte text, který přišel od cizího uživatele z internetu (XSS).
V našem případě text zadává sám autor stránky do vlastního prohlížeče,
takže riziko je nulové. Až budeme v 18. hodině nasazovat aplikaci veřejně,
zmíníme to jednou větou — teď to řešit nemusíte.
| Ukázka | Co ukazuje | Čas |
|---|---|---|
| 1 | Nadpisy, text, barevné zprávy, tlačítko | 8 min |
| 2 | Barevný markdown, HTML box, barva podle hodnoty | 10 min |
| 3 | Sidebar, sloupce, metriky, taby | 10 min |
| 4 | Kreslení po souřadnicích, obrázek řízený posuvníky | 10 min |
| 5 | Herní pole s prvky na přesných pozicích | 7 min |
st.title("PyQuest") na název vlastní hry a spusť to znovu.
Tohle je první pořádný „aha" moment.st.balloons() a všimni si, že tlačítko teď jen vypíše text.
Pak ho vrať zpátky. Každý řádek dělá právě jednu věc.st.error a st.success — všimni si, že se stránka
kreslí přesně v pořadí, v jakém jsou příkazy napsané.st.success(f"Vítej...") a nech to spadnout.
Přečti si hlášku IndentationError.
Pak odsazení vrať. Tohle je dobrý způsob, jak se naučit nebát se chyb.elif zivoty > 25:.60 a 25 na 90 a 80. Znovu táhni.
Teď je skoro pořád červená. Tady krásně vidíš, že ta čísla určuješ ty.border-radius: 12px na 0px a pak na 50px.
Rámeček se změní z kulatého na hranatý a pak na ovál.padding: 20px na 60px. Box se nafoukne. Tohle je nejjasnější
způsob, jak pochopit, co padding je.unsafe_allow_html=True u prvního boxu. Objeví se HTML jako text.
Takhle nejlíp uvidíš, k čemu ten parametr je.st.columns(2) na st.columns([3, 1]). Levý sloupec se roztáhne.
Pak zkus [1, 3] a nakonec [1, 1, 1] — to spadne, protože vlevo
jsou jen dvě jména. Přečti si hlášku: „not enough values to unpack"
znamená „je málo přihrádek na to, kolik jmen chceš".st.metric("Zlato", ...) dovnitř with levy:. Všimni si,
že se stejný příkaz může objevit kdekoliv a poslouchá to, kde je odsazený.layout="wide" na layout="centered". Stránka se zúží.
wide se hodí, když chceš víc místa vedle sebe, centered když má být obsah užší.st.tabs([...]) a nech ji prázdnou.
Uvidíš, že karta existuje, i když v ní nic není.border=True u kontejneru. Rámeček zmizí a hned uvidíš,
že True je tady vypínač.#87ceeb na #000000. Z dne se stane noc.
Pak zkus "red" — všimni si, že jdou psát i anglické názvy barev.[0, 200, 400, 300] na [0, 100, 400, 300]. Tráva zabere
půl obrázku. Zkus najít, které číslo za to může.[300, 20, 370, 90] na [20, 20, 90, 90].
Přesune se doleva. Všimni si, že se změnila obě X a obě zůstala
stejně daleko od sebe, takže velikost je pořád stejná.st.image(platno) (dej před něj #).
Obrázek zmizí, i když se pořád kreslí. Bez st.image se nic neukáže.top,
a to už tam je jako hrdina_y).left.
Zkus si vymyslet vlastní souřadnice a hned je zapsat.70% v gradientu na 40%. Obzor se posune, trávy je víc.overflow: hidden. Posuň hrdinu na kraj — teď vyleze
z pole ven. overflow:hidden funguje jako „ořezávátko".font-size:40px u hrdiny na 100px.
Hned uvidíš, že velikost emoji se řídí velikostí písma.Než se pustíš do cvičení, mrkni na tuhle tabulku. Chyby jsou normální součást programování a často stačí vědět, kam se podívat.
| Hláška nebo příznak | Příčina | Co udělat |
|---|---|---|
ModuleNotFoundError: streamlit |
Knihovna není nainstalovaná | python -m pip install streamlit |
command not found: streamlit |
Není v cestě | Zkusit python -m streamlit run app.py |
| Stránka se nemění | Neuložený soubor | Ctrl+S, zapnout Run on save |
Port 8501 is already in use |
Server už běží z minula | Ctrl+C ve starém terminálu |
| Vidí HTML jako obyčejný text | Chybí unsafe_allow_html=True |
Doplnit parametr |
| Prázdná stránka, divné hlášky | Spustili python app.py |
Musí být streamlit run app.py |
IndentationError |
Špatné odsazení pod if / with |
Zkontrolovat, že odsazení jsou 4 mezery |
| Tlačítko „nefunguje" | Kód není odsazený uvnitř if |
Totéž — odsazení |
| Obrázek je vzhůru nohama | Zapomněl jsi, že Y roste dolů | Vrátit se k nákresu souřadnic |
| Obrázek se nezobrazí vůbec | Chybí st.image(platno) |
Doplnit poslední řádek |
SyntaxError u f"..." |
Chybí f před uvozovkami |
Doplnit f |
Barvy :red[...] nefungují |
Použili st.title místo st.markdown |
Přepsat na st.markdown("# :red[...]") |
Použij tento postup:
Programátor není člověk, který nedělá chyby. Programátor je člověk, který je umí přečíst.
Tvoje zadání:
Vytvoř webovou vizitku svého hrdiny. Musí obsahovat:
- Nadpis se jménem hrdiny —
st.title- Podnadpis s povoláním —
st.headerast.subheader- Dvě věty o hrdinovi, kde alespoň jedno slovo je tučně —
st.markdowna**text**- Všechny čtyři barevné zprávy: zelenou, modrou, oranžovou a červenou
- Tlačítko „Vydat se na cestu", které po kliknutí něco vypíše
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–3 fungují |
| Rozšíření | Přidat st.divider() mezi sekce a st.caption() s poznámkou |
| Výzva | Přidat st.balloons() nebo st.snow() po kliknutí a emoji do nadpisu |
Očekávaný výsledek: stránka s nadpisem, popisem, čtyřmi barevnými pruhy a funkčním tlačítkem.
Kde se zaseknou:
if st.button(...). Zdaleka nejčastější problém dneška.
Dítě napíše if st.button("Jdi"): a další řádek nechá u kraje.
Python spadne na IndentationError. Ukažte, že za dvojtečkou
musí následující řádek začínat o čtyři mezery dál.if."Arkon's meč" nebo
'Arkonův meč'), rozbije se jim řetězec. Poraďte jim, ať používají
všude dvojité uvozovky a apostrofy zatím nepoužívají.**tučně** funguje jen v st.markdown, ne v st.write
(respektive st.write to zvládne taky, ale nespoléhejte na to a učte
je st.markdown).Kdo je hotový dřív: ať přidá st.metric("Zlato", 120, delta=25)
a st.progress(0.8). Obojí je jednořádkové a vypadá to profesionálně.
Otázka na závěr cvičení: „Kdo dokáže tlačítkem změnit něco jiného
než jen text?" Odpověď je st.balloons(), st.snow(), st.toast("...").
Tvoje zadání:
Vytvoř kartu hrdiny, která mění barvu podle jeho zdraví.
- Napiš jméno hrdiny barevně pomocí
:red[...],:blue[...]nebo:violet[...]- Přidej stav hrdiny se zvýrazněným pozadím
:orange-background[Zraněný]- Vytvoř tmavý box s rámečkem pomocí
st.markdownaunsafe_allow_html=True. Dej mupadding,border-radiusatext-align: center- Přidej posuvník
st.slider("Životy", 0, 100, 72)- Pomocí
if / elif / elsenastav barvu: nad 60 zelená, 26–60 oranžová, 25 a méně červená. Barvu použij v boxu a přidejst.progress()
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–3 |
| Rozšíření | Body 4–5, barva reaguje na posuvník |
| Výzva | Přidat textovou hlášku a st.color_picker na barvu rámečku |
Očekávaný výsledek: karta, u které tažením posuvníku dolů zeleň postupně přechází do oranžové a červené.
Kde se zaseknou:
f před uvozovkami. Napíšou """<div style="background:{barva}">"""
bez f a na stránce se objeví doslova {barva}. Tohle je nejčastější
chyba tohoto cvičení. Naučte je pravidlo: „Jsou uvnitř složené závorky?
Pak musí být před uvozovkami f."st.progress(zivoty) místo st.progress(zivoty / 100).
Spadne s hláškou, že hodnota musí být mezi 0 a 1.if zivoty > 25: jako první,
bude to oranžové i pro 100 životů. Vysvětlete, že se podmínky
zkoušejí odshora a první, která platí, vyhrává. Tohle je skvělá
příprava na 4. hodinu.elif a else.Rozdíl elif a druhého if ukažte na tabuli, když se někdo zeptá:
při if / elif se vybere právě jedna větev, při dvou samostatných if
můžou proběhnout obě.
Kdo je hotový dřív: ať přidá druhý posuvník na zlato a st.metric,
který ukazuje rozdíl oproti minulé hodnotě. Nebo ať zkusí st.color_picker
na barvu rámečku, jak je ve Výzvě.
Tvoje zadání:
Postav rozhraní souboje, jaké znáš z her.
- Přidej boční panel
with st.sidebar:a v něm výběr obtížnosti- Rozděl stránku:
levy, pravy = st.columns(2). Vlevo hráč, vpravo příšera. Každý má nadpis, emoji ast.progress()- Pod tím přidej řádek se čtyřmi
st.metric— zlato, úroveň, síla, lektvary. U zlata použijdelta=25- Přidej
st.tabs(["Souboj", "Inventář", "Deník"])- Do karty Souboj dej tři tlačítka vedle sebe ve sloupcích: Zaútočit, Vypít lektvar, Utéct
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–3 |
| Rozšíření | Body 4–5 |
| Výzva | st.columns([2, 1, 2]) s velkým „VS" uprostřed, st.container(border=True) |
Očekávaný výsledek: obrazovka připomínající RPG hru — dva soupeři vedle sebe, statistiky, záložky, ovládací tlačítka.
Kde se zaseknou:
a, b = st.columns(3) spadne
na ValueError: too many values to unpack. Přeložte tu hlášku nahlas:
„Chceš rozdělit na tři, ale pojmenoval jsi jen dvě."with. Napíšou levy, pravy = st.columns(2) a pak
normálně st.subheader(...) bez odsazení — všechno skončí pod sebou
přes celou šířku. Ukažte oba zápisy (with levy: i levy.subheader(...)).with levy: levy.write("x") funguje, ale je
matoucí. Řekněte, ať si vyberou jeden a drží se ho.st.set_page_config musí být první příkaz Streamlitu v souboru.
Když ho dají doprostřed, spadne to. Tohle je jediné místo v celém kurzu,
kde na pořadí opravdu záleží.Kdo je hotový dřív: Výzva se sloupci [2, 1, 2] a velkým „VS" uprostřed
udělá největší dojem. Ukažte mu st.markdown("<h1 style='text-align:center'>VS</h1>",
unsafe_allow_html=True).
Tip na atmosféru: Nechte tři děti ukázat svoji obrazovku souboje na projektoru. U tohohle cvičení bývají výsledky nejrozmanitější.
Tvoje zadání:
Nakresli erb svého rodu. Nekreslíš myší, ale čísly — souřadnicemi. Plátno je 300 × 360 pixelů, bod
[0,0]je vlevo nahoře a Y roste dolů.
- Vytvoř plátno a nakresli štít: obdélník
[40, 30, 260, 230]- Pod něj přidej špičku:
stetec.polygon([(40,230), (150,330), (260,230)], fill=...)- Doprostřed přidej znak — kruh (
ellipse), kříž (dva obdélníky) nebo trojúhelník- Přidej
st.color_pickerna barvu štítu a druhý na barvu znaku- Přidej
st.selectboxs výběrem tvaru znaku a pomocíif/elif/elsekresli podle výběru
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–3, erb se zobrazí |
| Rozšíření | Body 4–5, barvy a tvar jdou měnit |
| Výzva | Hvězda pomocí polygon s deseti body, text se jménem rodu |
Očekávaný výsledek: erb, u kterého změna barvy v color_picker
okamžitě překreslí obrázek.
Kde se zaseknou:
#ffd166.polygon. Body se spojují v tom pořadí,
v jakém jsou napsané. Když je prohodí, vznikne přesýpací hodiny
místo trojúhelníku. To je mimochodem hezký efekt — nechte je to zkusit.st.image(platno) na konci. Připomeňte to nahlas
celé třídě hned na začátku cvičení.stetec.text((60, 340), ...) je skoro u spodního
okraje plátna vysokého 360. Když napíšou 370, text zmizí.Znak uprostřed — nabídněte tyhle varianty, ať mají z čeho vybírat:
# Kruh
stetec.ellipse([110, 100, 190, 180], fill=barva)
# Kříž (dva obdélníky přes sebe)
stetec.rectangle([135, 80, 165, 200], fill=barva)
stetec.rectangle([100, 120, 200, 150], fill=barva)
# Trojúhelník
stetec.polygon([(150, 90), (200, 185), (100, 185)], fill=barva)
# Dva pruhy napříč
stetec.line([40, 100, 260, 100], fill=barva, width=12)
stetec.line([40, 160, 260, 160], fill=barva, width=12)
Kdo je hotový dřív: hvězda z deseti bodů (je v řešení) nebo
druhý erb vedle prvního pomocí st.columns(2).
Toto cvičení je první díl celoročního projektu. Ulož soubor jako
app.pya od příští hodiny ho budeme jenom rozšiřovat.
Tvoje zadání:
- Přidej
st.set_page_config(page_title="PyQuest", page_icon="⚔️")a nadpis hry- Přidej
st.text_inputna jméno hrdiny- Přidej
st.selectboxna povolání: Bojovník, Kouzelník, Lupič- Přidej
st.radios výběrem emoji postavy a parametremhorizontal=True- Přidej
st.slider("Kde stojí hrdina?", 0, 440, 40)a použij jeho hodnotu jakoleft:{hrdina_x}pxv herním poli. Nakonec přidej tlačítko „Začít dobrodružství"
| Úroveň | Co má zvládnout |
|---|---|
| Minimum | Body 1–3, jméno se vypíše na stránku |
| Rozšíření | Body 4–5, postava se posouvá po herním poli |
| Výzva | Další prvky v poli (stromy, mraky) a výpis aktuální pozice |
Očekávaný výsledek: funkční úvodní obrazovka hry, kde tažením posuvníku postavička chodí po louce směrem k hradu.
Kde se zaseknou:
f u trojitých uvozovek. Jakmile do HTML vloží
{hrdina_x}, musí být f""". Bez toho se na stránce objeví doslova
{hrdina_x} a postava se nehýbe. Tohle je nejčastější chyba
tohoto cvičení — čekejte ji minimálně u poloviny třídy.{hrdina_x}
do obou divů.st.set_page_config není první. Musí být hned po import.Zdůrazněte, že tohle je start celoročního projektu. Ať si soubor
uloží pod jménem app.py do složky, kterou si zapamatují. Nejlépe ať si
hned vytvoří složku pyquest na ploše. Kdo pracuje na školním počítači,
ať si soubor pošle e-mailem nebo uloží na flashku.
Poslední pět minut hodiny: promítněte tři až čtyři výsledky. Nejde o to najít nejlepší — jde o to, aby každý viděl, že ostatní mají něco jiného, a přesto to funguje.
Uprav svůj soubor
app.pytak, aby úvodní obrazovka PyQuestu obsahovala:
- alespoň pět různých prvků na herním poli (postava, hrad, stromy, mraky, slunce),
- vlastní barevné schéma pozadí,
- alespoň jeden
color_pickerneboselectbox, kterým se dá vzhled změnit,- vlastní název hry místo „PyQuest".
Ulož snímek obrazovky a přines na příští hodinu.
Úkol je schválně otevřený — nejde o správnou odpověď, ale o to, aby si dítě sedlo doma k počítači a znovu si otevřelo VS Code. Pokud to udělá, návyk je založený.
Na začátku příští hodiny si vyhraďte pět minut na promítnutí tří až pěti domácích úkolů. Nehodnoťte správnost, komentujte nápady. Kdo úkol nemá, nic se neděje — 2. hodina začíná od nuly u proměnných.
Zálohujte za ně. Řekněte jim, ať vám soubor app.py pošlou
e-mailem nebo do sdílené složky. Za tři měsíce budete rádi,
že máte zálohu, když někomu spadne notebook.
Toto je jedna z možných variant, jak mohl úkol dopadnout. Tvoje řešení se může lišit a to je v pořádku.
Oficiální dokumentace je místo, kam se programátoři chodí podívat, když si chtějí něco ověřit nebo zjistit víc detailů. Je většinou v angličtině, ale to nevadí — zkus se orientovat podle názvu funkce, ukázkového kódu a obrázků.
| Co jsme použili | Oficiální dokumentace | Co tam najdeš |
|---|---|---|
st.title |
st.title |
velký nadpis stránky a parametry |
st.header |
st.header |
nadpis sekce a ukázky použití |
st.write |
st.write |
univerzální výpis textu, čísel i objektů |
st.markdown |
st.markdown |
formátovaný text, Markdown a HTML |
st.success |
st.success |
zelená stavová zpráva a možnosti |
st.info |
st.info |
informační modrá hláška a příklady |
st.warning |
st.warning |
varování a doporučené použití |
st.error |
st.error |
chybová hláška a vzhled boxu |
st.metric |
st.metric |
velké číslo, delta a formát |
st.progress |
st.progress |
progress bar a očekávané hodnoty |
st.text_input |
st.text_input |
textové pole a jeho nastavení |
st.slider |
st.slider |
posuvník, minimum, maximum i výchozí hodnotu |
st.selectbox |
st.selectbox |
rozbalovací výběr z možností |
st.checkbox |
st.checkbox |
přepínač ano/ne a návratovou hodnotu |
st.radio |
st.radio |
volbu jedné možnosti ze seznamu |
st.color_picker |
st.color_picker |
výběr barvy a hex kód |
st.columns |
st.columns |
rozdělení stránky do sloupců |
st.sidebar |
st.sidebar |
postranní panel pro ovládací prvky |
st.tabs |
st.tabs |
záložky a přepínání obsahu |
st.expander |
st.expander |
rozbalovací sekci pro detaily |
st.container |
st.container |
seskupení prvků do jednoho bloku |
st.button |
st.button |
tlačítko a co vrací po kliknutí |
st.image |
st.image |
zobrazení obrázku a popisek |
ImageDraw (Pillow) |
PIL.ImageDraw |
kreslení čar, tvarů a výplní |
Pro rychlejší studenty, kteří dokončí cvičení dřív, nebo na posledních 10–15 minut.
| Cvičení | Odkaz | Proč se hodí |
|---|---|---|
| Programování v Pythonu | umimeinformatiku.cz | Základní syntaxe, volání funkcí |
| Python želva | umimeinformatiku.cz | Souřadnice a kreslení — navazuje na cvičení 4 |
| Želví grafika | umimeinformatiku.cz | Pořadí příkazů při kreslení |
Želví grafika je zde obzvlášť vhodná, protože procvičuje přesně tu dovednost, kterou děti právě použily — přemýšlet o obrázku jako o posloupnosti souřadnic a příkazů.
Nedávejte to celé třídě naráz. Použijte to jako záložní aktivitu pro tři až pět nejrychlejších dětí, aby nerušily ostatní. Mějte odkaz připravený v záložkách prohlížeče, ať ho nemusíte hledat.