Generování objektů na formuláři za běhu aplikace

13. února 2008 11:39
programování

Na začátku února jsem se během výuky programování ve Visual Basicu .net 2.0 dostal k dynamickému generování objektů (komponent) za běhu aplikace. Nejprve jsme s žáky zkoušeli jen přidávat další a další tlačítka, v následující hodině jsme pak vyzkoušeli vytvořit jednoduchou aplikaci, která umí ze souboru načíst libovolné hrací pole a to na formuláři z obrázků vytvořit.

V tomto článku se pokusím shrnout postup, jak objekty za běhu do Containeru (např. formulář, panel,…) generovat. A také stručně popíšu postup, jak generovat objekty obrázkového hracího pole předem vytvořeného v textovém souboru.

Postup přidání komponent za běhu

Postup dynamického generování objektů je celkem snadný, stačí udělat následujicí 3 (až 4) kroky a je to:

  1. Vytvoření proměnné obsahující novou instanci požadovaného objektu (komponenty)

    např. Dim tlacitko As New Button()

  2. Nastavení protřebných vlastností nového objektu

    Pokud jde o viditelné objekty, je nutné nastavit alespoň rozměry Size a umístění Location.

    např. tlacitko.Size = New Size(50, 25)

  3. Přiřazení obslužné procedury požadované události

    Pokud nepotřebujete, aby dynamicky přidaný objekt umožňoval nějakou událost (např. kliknutí) obsluhovat, není tento krok potřeba vůbec řešit.

    např.: AddHandler tlaciko.Click, New System.EventHandler(AddressOf Tlacitko_Click)

  4. Vložení připraveného objektu do kolekce objektů

    Do skupiny kontejnerů, do kterých lze objekty vkládat, patří např. formulář, panel,…

    např. Me.Controls.Add(tlacitko)

Kód pro přidání objektu PictureBox na Panel

Private Sub PridejObrazek()

    'Procedura vytvoří nové obrázkové políčko na fomuláři
    'a přiřadí mu proceduru pro obsluhu události kliknutí

    'krok 1: deklarace proměnné
    Dim policko As New PictureBox()

    'krok 2: nastavení potřebných vlastností
    policko.Size = New Size(25, 25)
    policko.Location = New Location(10, 20)
    policko.Image = imgTrava.Image

    'krok 3: přidání ovladače události kliknutí na obrázkové políčko
    AddHandler policko.Click, New System.EventHandler(AddressOf Policko_Click)

    'krok 4: vložení vygenerováného objektu na formulář
    Me.Controls.Add(policko)

End Sub

Private Sub Policko_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

    'Procedura obsluhující kliknutí na políčko hracího pole

    'přetypování senderu na objekt PictureBox, abychom s ním mohli pracovat
    Dim policko As PictureBox = CType(sender, PictureBox)

    'zobrazení informací o obrázkovém hracím políčku, na které bylo kliknuto
    MsgBox("Kliknuto na políčko s následujícími vlastnostmi: " + vbCrLf + _
      " pozice: [" + policko.Left.ToString() + "," + policko.Top.ToString() + "]" + vbCrLf + _
      " rozměr: [" + policko.Width.ToString() + "," + policko.Height.ToString() + "]")

End Sub

Procedura Tlacitko_Click zajišťuje obsluhu kliknutí na obrázkové políčko PictureBox. Pokud by měla řešit jinou událost než Click, musela by mít odpovídající typ parametru e. Tyto definice lze samozřejmě snadno nalézt v nápovědě MSDN.

Vytvoření komplexnější aplikace

Nyní již umíme vygenerovat dynamicky za běhu objekt a přiřadit k němu i obsluhu nějaké události, proto můžeme naši aplikaci rozšířit.

Naše aplikace bude umět vygenerovat libovolné hrací pole obsahující dva typy polí zeď a trávu. To jak hrací pole bude vypadat, bude určeno v textovém souboru, který bude do aplikace moci uživatel načíst.

Ukázka prostředí aplikace

ukázka prostředí programu

Řešení načítání hracího pole ze souboru

Textový soubor obsahuje definici tvaru hracího pole: 1 – zeď, 0 – tráva/volná plocha a je uložen v samostatném souboru někde na disku.

11111111111111111111
10000000000000000001
10000111111100000001
11100001100000000001
11100000000000000001
11111111111111111111

V programu pak budeme po připojení k textovému souboru plánu hracího pole načítat jeden řádek za druhým a každý řádek samostatně zpracovávat procedurou ZpracujRadek(radek As String, cisloRadku As Integer).

Private Sub ZpracujRadek(ByVal radek As String, ByVal cislo As Integer)

    'postupně čteme ze řádku znak po znaku
    For i As Integer = 0 To radek.Length - 1

       'negerujeme jednotlivá políčka hrací plochy
       Dim policko As New PictureBox()
       policko.Size = New Size(25, 25) 'nastavujeme velikost obrázku
       'umístění na správnou pozici (vypočítá z čísla řádku a pozice znaku)
       policko.Location = New Point(i * policko.Width, cislo * policko.Height)
       policko.Tag = i + (cislo * radek.Length)

       'zvolení správného obrázku (rozhodujeme se podle jednoho znaku)
       Dim znak As Char = radek.Substring(i, 1)
       Select Case znak
          Case "1"
              'zobrazí obrázek zdi
              policko.Image = imgZed.Image
          Case Else
              'zobrazí obrázek plochy
              policko.Image = imgPlocha.Image
       End Select

       'přidání ovladače události kliknutí na obrázkové políčko
       AddHandler policko.Click, New System.EventHandler(AddressOf Policko_Click)

       'vložení obrázku na plochu
       pnlPlocha.Controls.Add(policko)

    Next

End Sub

A teď již nejsme daleko od výsledné aplikace, kterou naleznete v přiloženém ukázkovém projektu. Jen ještě upozorním na několik skutečností, které výsledný projekt reflektuje.

  • na formuláři je nutné mít umístěné alespoň 2 PictureBoxy obsahující obrázky zdi a trávy,
  • dynamicky vytvářené PictureBoxy jsou vkládány na Panel nazvaný pnlPlocha,
  • pro výběr souboru hrací plochy k načtení je použit objekt OpenFileDialog,
  • obsluha události kliknutí na PictureBox je značně rozšířena a umožňuje zobrazovat na políčcích trávy umisťovat postavičku, která se dalším kliknutím přesouvá.

Ukázkový projekt ke stažení

Pokud si chcete celý projekt vyzkoušet a projít všechny jeho části, máte příležitost na mém ukázkovém webu.

jerrysohn | trvalý odkaz | přidej komentář

Osadníci z Katanu – hledání nejdelší cesty

13. června 2006 15:13
programování

Konečně na svůj blog mohu napsat něco z mého oboru a z toho co mě kromě skautingu zajímá nejvíce. Přichází první článek o programování, nebo spíše o jednom konkrétním programu. I když vlastně možná by to spíše mělo být v rubrice škola, neboť jde o semestrální práci z teoretické informatiky, kterou jsem dnes úspěšně odevzdal.

A o co tedy vlastně jde? Jde o program, který využívá znalostí z teorie grafů a možnosti převedení relativně běžných problémů na problémy nad grafy.

Možná znáte deskovou hru Osadníci z Katanu (The Settlers of Catan). U nás v roverském kmeni je docela oblíbená a já osobně také jeden exemplář vlastním. Můj program řeší část hry, kdy se zjišťuje, který z hráčů má nejdelší cestu, za kterou získá prémiové body do celkového hodnocení. Jde tedy o zajímavou úlohu nad grafy – hledání nejdelší cesty.

Není to vlastně tak úplně standardní úloha, neboť běžné grafové algoritmy řeší problém hledání nejkratší cesty. Proto jsem se při svém řešení rozhodl na problematiku podívat trošku opačně. Prostě jsem jen zkusil vzít klasický Dijkstrův algoritmus, který hledá nejkratší cestu a při relaxaci – tedy porovnání ohodnocení již objevených cest a modifikaci volby na tu nejkratší – volím naopak cestu nejdelší. Tím ve výsledku dociluji toho, že algoritmus najde nejdelší cestu.

Při realizaci programu využívám pro reprezentaci grafu v paměti spojových seznamů, polí a vlastní prioritní fronty, která umí zpracovávané uzly vždy seřadit do potřebného pořadí.

Pokud by vás prográmek zajímal, celý jej níže přikládám. A ještě taková jedna drobnost, i přes to že s oblibou programuji ve Visual Basicu .NET, tohle jsem napsal celé v C#. A to i s využitím některých nových skvělých vlastností platformy .NET 2.0. Takže jsem si zkusil zase něco super, co mi opět ukázalo ohromnou sílu platformy Microsoft .NET a také jsem odevzdal program v syntaxi „blízké jazyku C“, který je na naší katedře až nechutně zakořeněn. I z toho důvodu mě velmi potěšil zájem mého cvičícího o C# a platformu .NET právě díky mé odevzdávané práci.

jerrysohn | trvalý odkaz | komentáře (4)

nahoru | na titulní stranu | redakce | provozováno na redakčním systému Gryphoon Weblog v1.82 (1.82.3061.33029)