IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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 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 - WPF - Okenní aplikace v C# .NET

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 - WPF - Okenní aplikace v C# .NET

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#

 

Předchozí článek
Řešené úlohy k 6.-10. lekci WPF v C# .NET
Všechny články v sekci
WPF - Okenní aplikace v C# .NET
Přeskočit článek
(nedoporučujeme)
Zpracování kliknutí na obdélník v C# .NET WPF
Článek pro vás napsal Radek Němec
Avatar
Uživatelské hodnocení:
39 hlasů
Autor začínal programovat v jazyce C# a během vysoké školy se naučil další programovací jazyky. Pracoval jsem jako programátor mobilních aplikací na platformě iOS a nyní jsem se opět vrátil k C# a zajímám se o webové technologie v ASP.NET Core.
Aktivity