Lekce 11 - Kreslení na Canvas v C# .NET WPF
V předešlém cvičení, Řešené úlohy k 6.-10. lekci WPF v C# .NET, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
Dnešní C# .NET WPF tutoriál budeme věnovat kreslení.
Kreslení na Canvas
Vytvoříme aplikaci, která má za úkol zastřešit prodej vstupenek do
kina. Jak víme, v sálu je mnoho sedadel a pracovník kina by měl v aplikaci
vidět, která sedadla jsou již obsazená. Možná by vás napadlo naklikat pro
sedadla Button
y. Pokud by však kino mělo 15 řad a každá řada
30 sedadel, máme to 450 Button
ů. Asi tušíte, že existuje
lepší cesta, než začít bušit Button1
, Button2
...
A jak by se potom obsluhovaly? V případě, že potřebujeme vykreslit něco
náročnějšího, než jen jeden nebo dva obrázky, využijeme
Canvas
, česky plátno. To spočívá v tom, že na formulář
umístíme jeden Canvas
a do něj budeme
vykreslovat to, co potřebujeme.
Aplikaci značně zjednodušíme, není třeba, aby byla složitá. Bude umět zobrazit jen jeden sál, který bude zpočátku prázdný. Uživatel nakliká myší obsazená sedadla a poté stiskne tlačítko "Uložit", které do zvolené lokace uloží jednoduchý txt soubor s informací o obsazenosti sálu. Ukládání si zkusíme proto, abychom se naučili pracovat s dialogy.
Návrh formuláře
Vytvořte si novou WPF Aplikaci, titulek okna nastavme na
Evidence kinosálu
. Oknu nastavte vlastnost
WindowStartupLocation
na hodnotu CenterScreen
. Tím
zajistíme, že se okno při spuštění aplikace zobrazí ve středu
obrazovky.
Pro návrh formuláře využijeme z předešlých lekcí již jistě dobře
známý prvek Grid
. Vzhled aplikace není nikterak složitý, a tak
si mřížku rozdělíme na dva řádky. Jeden řádek bude obsahovat
Canvas
a ve druhém bude Button
s textem
Uložit
. U tlačítka si ještě přidáme událost
Click
a necháme si vygenerovat metodu v Code Behind, která se
vždy zavolá, když uživatel na tlačítko klikne. Váš formulář by měl
vypadat asi takto:
A zde je jeho odpovídající XAML kód:
<Window x:Class="Kino.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-;;compatibility/2006" xmlns:local="clr-namespace:Kino" mc:Ignorable="d" Title="Evidence kinosálu" WindowStartupLocation="CenterScreen" Height="450" Width="600"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="350"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Canvas Name="MyCanvas" Margin="20 50 0 0"></Canvas> <Button Name="Ulozit" Click="Ulozit_Click" Content="Uložit" Grid.Row="1" Height="20" Width="100"></Button> </Grid> </Window>
Logická vrstva
Asi vás nepřekvapí, že k aplikaci přidáme třídu Kinosal
.
Bude mít jeden privátní atribut, kterým bude dvourozměrné pole
sedadel. Pokud jste s 2D polem ještě nepracovali, tak si ho můžete
představit jako tabulku. Jednorozměrné (klasické) pole je vlastně jen jeden
řádek. S 2D polem poté pracujeme úplně stejně, jako s jednorozměrným,
jen musíme uvést dvě souřadnice (X a Y). V mnoha jazycích se dělá 2D pole
jako pole polí, C# umí definovat přímo 2d pole a to takto:
class Kinosal { private bool[,] sedadla = new bool[30, 15]; }
Sedadla jsou typu bool
, protože nás zajímá jen jestli je
volné nebo obsazené. 30
je šířka pole, 15
jeho
výška.
Do třídy ještě přidáme 2 privátní konstanty, jedna udává velikost vykreslovaného sedadla v pixelech a druhá mezeru mezi sedadly v pixelech. Zvykněte si konstanty používat, až budete chtít sedadla zvětšit, stačí pouze přepsat jednu konstantu a nemusíte luštit vykreslovací kód.
private const int velikost = 16; private const int mezera = 2;
Můžeme přejít k metodám.
Vložení obdélníků
Již jsme si zmínili, že budeme kreslit na plátno. Jednotlivé obdélníky
reprezentující sedadla budou reprezentované jako objekty, které na plátno
vložíme pomocí metody VlozObdelniky()
. Toto plátno je typu
Canvas
a necháme si ho přijít v parametru metody. Je potřeba
přidat jmenný prostor using System.Windows.Shapes
, který nám
zpřístupní třídu Rectangle
(obdélník). Když budeme
jednotlivé obdélníky vkládat na Canvas
, tak jim vždy
nastavíme šířku a výšku na konstantu velikost
a dále
nastavíme příslušnou barvu ve vlastnosti Fill
pomocí statické
třídy Brushes
. Ta obsahuje hotové instance nastavené na
určité barvy, stačí si jen vybrat.
Pomocí dvou vnořených cyklů projedeme všechna sedadla v poli a na
plátno vykreslíme buď zelený nebo červený čtverec. Vnějším cyklem
budeme projíždět řádky, vnitřním sloupce v aktuálním řádku. Barvu
(přesněji štětec) určíme podle toho, zda je sedadlo na dané souřadnici
true
nebo false
. Kód metody bude následující:
public void VlozObdelniky(Canvas MyCanvas) { for (int j = 0; j < sedadla.GetLength(1); j++) { for (int i = 0; i < sedadla.GetLength(0); i++) { Rectangle rectangle = new Rectangle { Height = velikost, Width = velikost, }; rectangle.Fill = sedadla[i, j] ? Brushes.Red : Brushes.Green; MyCanvas.Children.Add(rectangle); Canvas.SetLeft(rectangle, i * (velikost + mezera)); Canvas.SetTop(rectangle, j * (velikost + mezera)); } } }
Všimněte si, že v cyklech nepoužíváme hodnoty 30
a
15
, ale používáme metodu GetLength()
s parametry
0
a 1
. Tato metoda slouží pro získání velikosti
dvourozměrného pole. 0
je šířka, 1
je výška
(samozřejmě záleží na nás, kterou dimenzi si určíme jako výšku a
kterou jako šířku).
Pevnou velikost neuvádíme pochopitelně z důvodu, že v
budoucnu můžeme pole zvětšit/zmenšit a museli bychom v kódu hledat kde
všude jsme hodnoty 30
a 15
použili. Těmto
problémům je vždy lepší se vyhnout a pracovat s délkou pole.
Za zmínku stojí i samotné vykreslení obdélníku. Můžeme vidět, že
vykreslení probíhá tak, že se každá instance Rectangle
přidá jako potomek do našeho Canvasu
. Potom aby se obdélníky
zobrazily přesně tam, kde chceme, tak je nutné ještě nastavit jejich
pozici. Využijeme statickou třídu Canvas
, která obsahuje metody
SetLeft()
a SetTop()
, které představují souřadnice
levého horního rohu obdélníku. Jelikož je každé sedadlo široké
16
pixelů + 2
pixely mezera, musíme jeho souřadnici
touho hodnotou pronásobit. Pokud je v i
např. hodnota
2
(kreslíme tedy 3. sloupec), kreslíme na X souřadnici
36
, nikoli na 2
To samé platí pro souřadnici
Y.
Propojení formuláře s logickou vrstvou
Základ logiky máme hotový, pojďme ji propojit s formulářem. Přejdeme do Code Behind formuláře a vytvoříme privátní instanci kinosálu:
private Kinosal kinosal = new Kinosal();
Nyní už je to opravdu velmi jednoduché. Na instanci kinosálu zavoláme
metodu VlozObdelniky()
a jako parametr jí předáme náš
Canvas
, který jsme si definovali ve formuláři. Aby došlo k
vykreslení při startu aplikace, tak tento kód umístěte v Code Behind do
konstruktoru formuláře.
public MainWindow()
{
InitializeComponent();
kinosal.VlozObdelniky(MyCanvas);
}
Za výsledek se nemusíme stydět:
V příští lekci, Zpracování kliknutí na obdélník v C# .NET WPF, si ukážeme, jak kliknutím na určité sedadlo změnit jeho stav a zprovozníme také ukládání. Projekt máte jako vždy ke stažení v příloze pro případ, že se vám něco nepodařilo.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 156x (374.47 kB)
Aplikace je včetně zdrojových kódů v jazyce C#