C# týden C# týden
Pořádné programy s pořádnou klávesnicí zdarma. Více zde
Pouze tento týden sleva až 80 % na C# .NET

Lekce 11 - Kreslení na Canvas v C# .NET WPF

C# .NET Formuláře WPF Kreslení na Canvas v C# .NET WPF

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Upomínač narozenin v C# .NET WPF - Serializace a dokončení, jsme dokončili tvorbu upomínače narozenin. Vyzkoušeli jsme si na něm základní formulářové prvky a také bindingy a práci s chybovými stavy. Již umíme vytvořit poměrně sofistikované aplikace. 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 Buttony. 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:

Kreslení na Canvas v C# .NET WPF

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:

Kreslení na anvas v C# NET WPF

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.


 

Stáhnout

Staženo 7x (374.47 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

 

Článek pro vás napsal Radek Němec
Avatar
Jak se ti líbí článek?
1 hlasů
Autor se věnuje především programování v jazyce C#. Postupně se chci naučit Javu a začít dělat i mobilní aplikace na IOS
Aktivity (6)

 

 

Komentáře

Avatar
Andy Scheuchzer:22. ledna 18:57

Nevím proč, ale něco mi tu chybí :-)

Váš formulář by měl vypadat asi takto:

…a obrázek nikde.

Projekt máte jako vždy ke stažení v příloze pro případ, že se vám něco nepodařilo.

…a zase nic.
A možná by neuškodilo počítat s proměnnou velikostí sálu i u plátna (nastavit jeho velikost a případně použít ScrollViewer).

Ale až na tyhle drobnosti je článek skvělý.

Odpovědět 22. ledna 18:57
Člověk, co si myslí, že snědl všechnu moudrost světa, i když tomu tak není.
Avatar
Ondřej Čech:25. ledna 14:10

Hodily by se tam dodelat mezery pro schody ;-) Jinac dobry

 
Odpovědět  +1 25. ledna 14:10
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.