11. diel - Kreslenie na Canvas v C # .NET WPF
V predchádzajúcom cvičení, Riešené úlohy k 6.-10. lekciu WPF v C # .NET, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.
V minulej lekcii, Riešené úlohy k 6.-10. lekciu WPF v C # .NET , sme dokončili tvorbu pripomienkovej narodenín. Vyskúšali sme si na ňom základné formulárové prvky a tiež binding a prácu s chybovými stavmi. Už vieme vytvoriť pomerne sofistikované aplikácie. Dnešné C# .NET WPF tutoriál budeme venovať kreslenie.
Kreslenie na Canvas
Vytvoríme aplikáciu, ktorá má za úlohu zastrešiť predaj vstupeniek do
kina. Ako vieme, v sály je veľa sedadiel a pracovník kina by mal v aplikácii
vidieť, ktorá sedadlá sú už obsadená. Možno by vás napadlo naklikať pre
sedadlá Button y. Ak by však kino malo 15 radov a každá rada 30
sedadiel, máme to 450 Button ov. Asi tušíte, že existuje
lepšia cesta, než začať búšiť Button1,
Button2... A ako by sa potom obsluhovali? V prípade, že
potrebujeme vykresliť niečo náročnejšieho, než len jeden alebo dva
obrázky, využijeme Canvas, česky plátno. To spočíva v tom,
že na formulár umiestnime jeden Canvas a do neho
budeme vykresľovať to, čo potrebujeme.
Aplikáciu značne zjednodušíme, nie je potrebné, aby bola zložitá. Bude vedieť zobraziť len jeden sála, ktorý bude spočiatku prázdny. Užívateľ naklikať myšou obsadená sedadla a potom stlačí tlačidlo "Uložiť", ktoré do zvolenej lokácie uloží jednoduchý txt súbor s informáciou o obsadenosti sály. Ukladanie si skúsime preto, aby sme sa naučili pracovať s dialógmi.
Návrh formulára
Vytvorte si novú WPF Aplikáciu, titulok okna nastavme na
Evidence kinosálu. Oknu nastavte vlastnosť
WindowStartupLocation na hodnotu CenterScreen. Tým
zabezpečíme, že sa okno pri spustení aplikácie zobrazí v strede
obrazovky.
Pre návrh formulára využijeme z predošlých lekcií už iste dobre známy
prvok Grid. Vzhľad aplikácie nie je nijako zložitý, a tak si
mriežku rozdelíme na dva riadky. Jeden riadok bude obsahovať
Canvas a v druhom bude Button s textom
Uložit. U tlačidla si ešte pridáme udalosť Click
a necháme si vygenerovať metódu v Code Behind, ktorá sa vždy zavolá, keď
používateľ na tlačidlo klikne. Váš formulár by mal vyzerať asi
takto:

A tu je jeho zodpovedajúce 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 neprekvapí, že k aplikácii pridáme triedu Kinosal.
Bude mať jeden privátne atribút, ktorým bude dvojrozmerné pole
sedadiel. Ak ste s 2D poľom ešte nepracovali, tak si ho môžete predstaviť
ako tabuľku. Jednorozmerné (klasické) pole je vlastne len jeden riadok. S 2D
poľom potom pracujeme úplne rovnako, ako s jednorozmernými, len musíme
uviesť dve súradnice (X a Y). V mnohých jazykoch sa robí 2D pole ako pole
polí, C# vie definovať priamo 2d poľa a to takto:
class Kinosal { private bool[,] sedadla = new bool[30, 15]; }
Sedadlá sú typu bool, pretože nás zaujíma len či je
voľné alebo obsadené. 30 je šírka poľa, 15 jeho
výška.
Do triedy ešte pridáme 2 privátne konštanty, jedna udáva veľkosť vykreslovaného sedadla v pixeloch a druhá medzeru medzi sedadlami v pixeloch. Zvyknite si konštanty používať, až budete chcieť sedadlá zväčšiť, stačí len prepísať jednu konštantu a nemusíte lúštiť vykresľovací kód.
private const int velikost = 16; private const int mezera = 2;
Môžeme prejsť k metódam.
Vloženie obdĺžnikov
Už sme si spomenuli, že budeme kresliť na plátno. Jednotlivé obdĺžniky
reprezentujúci sedadlá budú reprezentované ako objekty, ktoré na plátno
vložíme pomocou metódy VlozObdelniky(). Toto plátno typu
Canvas a necháme si ho prísť v parametri metódy. Je potrebné
pridať menný priestor using System.Windows.Shapes, ktorý nám
sprístupní triedu Rectangle (obdĺžnik). Keď budeme jednotlivé
obdĺžniky vkladať na Canvas, tak im vždy nastavíme šírku a
výšku na konštantu velikost a ďalej nastavíme príslušnú
farbu vo vlastnosti Fill pomocou statickej triedy
Brushes. Tá obsahuje hotové inštancie nastavenej na určité
farby, stačí si len vybrať.
Pomocou dvoch vnorených cyklov prejdeme všetky sedadlá v poli a na plátno
vykreslíme buď zelený alebo červený štvorec. Vonkajším cyklom budeme
prechádzať riadky, vnútorným stĺpce v aktuálnom riadku. Farbu (presnejšie
štetec) určíme podľa toho, či je sedadlo na dané súradnici
true alebo false. Kód metódy bude nasledujúci:
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šimnite si, že v cykloch nepoužívame hodnoty 30 a
15, ale používame metódu GetLength() s parametrami
0 a 1. Táto metóda slúži na získanie veľkosti
dvojrozmerného poľa. 0 je šírka, 1 je výška
(samozrejme záleží na nás, ktorú dimenziu si určíme ako výšku a ktorú
ako šírku).
Pevnú veľkosť neuvádzame pochopiteľne z dôvodu, že v
budúcnosti môžeme pole zväčšiť / zmenšiť a museli by sme v kóde
hľadať kde všade sme hodnoty 30 a 15 použili.
Týmto problémom je vždy lepšie sa vyhnúť a pracovať s dĺžkou poľa.
Za zmienku stojí aj samotné vykreslenie obdĺžnika. Môžeme vidieť, že
vykreslenie prebieha tak, že sa každá inštancia Rectangle
pridá ako potomok do nášho Canvasu. Potom aby sa obdĺžniky
zobrazili presne tam, kde chceme, tak je nutné ešte nastaviť ich pozíciu.
Využijeme statickú triedu Canvas, ktorá obsahuje metódy
SetLeft() a SetTop(), ktoré predstavujú súradnice
ľavého horného rohu obdĺžnika. Keďže je každé sedadlo široké 16
pixelov + 2 pixely medzera, musíme jeho súradnicu za večnými hodnotou
prenásobiť. Pokiaľ je v i napr. Hodnota 2
(kreslíme teda 3. stĺpec), kreslíme na X súradnicu 36, nie na
2
To isté platí
pre súradnicu Y.
Prepojenie formuláre s logickou vrstvou
Základ logiky máme hotový, poďme ju prepojiť s formulárom. Prejdeme do Code Behind formulára a vytvoríme privátne inštanciu kinosály:
private Kinosal kinosal = new Kinosal();
Teraz už je to naozaj veľmi jednoduché. Na inštanciu kinosály zavoláme
metódu VlozObdelniky() a ako parameter jej odovzdáme náš
Canvas, ktorý sme si definovali vo formulári. Aby došlo k
vykreslenie pri štarte aplikácie, tak tento kód umiestnite v Code Behind do
konstruktoru formulára.
public MainWindow()
{
InitializeComponent();
kinosal.VlozObdelniky(MyCanvas);
}
Za výsledok sa nemusíme hanbiť:

V budúcej lekcii, Spracovanie kliknutí na obdĺžnik v C # .NET WPF , si ukážeme, ako kliknutím na určité sedadlo zmeniť jeho stav a sprevádzkujeme tiež ukladanie. Projekt máte ako vždy k stiahnutiu v prílohe pre prípad, že sa vám niečo nepodarilo.
