Serwis internetowy netmax.pl
Komputery    
Poprzedni artykuł Następny artykuł

Delphi, cz. 9

Adam Boduch

W poprzednim rozdziale omawiana była grafika. Oczywiście nie wyczerpałem tematu. Będziemy się tym zajmować jeszcze w tym i następnym rozdziale. Nim to jednak nastąpi trochę trudniejsze zagadnienia z języka Pascal.

Tablice

Tablica zbiór elementów tego samego typu. Wiem, że nie brzmi to przekonywująca, ale popatrz na poniższy przykład:

var
  Tablica : array[0..1] of String;

Powyżej została zadeklarowana 2 elementowa tablica ( zero to też element ) typu String. Konstrukcja zawsze będzie taka sama. Najpierw nazwa tablicy, następnie słowo array, w nawiasie określa się elementy tablicy. Następnie słowo of, a na samym końcu typ tablicy. Dopiero zadeklarowałeś tablice - teraz trzeba ją uzupełnić - robi się to tak:

Tablica[0] := 'Adam';
Tablica[1] := 'Boduch';

Nastąpiło tutaj wypełnienie elementów tablicy. Podawana jest nazwa tablicy, następnie fragment, który ma być uzupełniony - w tym wypadku numer tablicy do wypełnienia. Teraz najważniejsze pytanie: po co stosować tablice? Jeżeli musisz zadeklarować wiele zmiennych tego samego typu - np.:

var
  Zmienna1: String;
  Zmienna2: String;
  Zmienna3: String;
begin
  Zmienna1 := 'My ';
  Zmienna2 := 'name ';
  Zmienna3 := 'is Bond ';
  ShowMessage(Zmienna1 + Zmienna2 + Zmienna3);

Powoduje to wyświetlenie na ekranie napisu: "My name is Bond". Po pierwsze jest to trochę nieestetyczne, a po drugie wymaga więcej pisania - nie lepiej by to było zrobić tak:

var
  Tablica: array[1..3] of String;
begin
  Tablica[1] := 'My ';
  Tablica[2] := 'name ';
  Tablica[3] := 'Bond';
  ShowMessage(Tablica[1] + Tablica[2] + Tablica[3]);

Czy nie lepiej to wygląda? Powoduje taki sam efekt. Specjalnie zadeklarowałem tablice z przedziału od 1 do 3 by pokazać, że wcale nie musi się to odbywać od zera. 
Istnieje także możliwość przydzielania elementów tablicy w sposób dynamiczny. Czyli kiedy nie znamy podczas pisania programu wielkości, jaką ma mieć ta tablica możemy to zrobić w sposób dynamiczny ( nowość w Delphi 4 ):

var
  Tablica : array of String;
begin
  SetLength(Tablica, 2); // przydzielenie tablicy 2-óch elementów
  Tablica[0] := 'Adam ';
  Tablica[1] := 'Boduch';
  ShowMessage(Tablica[0] + Tablica[1]);

Zauważ, że podczas deklaracji zmiennej tablicy nie podany został jej zakres. Dokonaliśmy to dopiero za pomocą polecenia "SetLength", w której jako pierwszy parametr podawana jest nazwa tablicy, a drugi to jej rozmiar ( w tym wypadku dwa elementy ). Dalej następuje już wypełnienie tablicy.

Rekordy

Rekordy są to stałe, które przechowują inne zmienne. Jest to taka paczka, która w ładnym opakowaniu przechowuje inne zmienne. Oto jak wygląda rekord - umieść go w sekcji Interface:

type
  TRecord = record
    Imie : String;
    Nazwisko: String;
    Kod: Integer;
  end;

Za słowem "type" deklarowany jest nowy typ ( nowy rekord ). Za słowem "record" następują zmienne, które do tego rekordu przynależa. Teraz, żeby taki rekord "wypełnić" w procedurze musisz napisać tak:

var
  Rec : TRecord;
begin
  Rec.Imie := 'Adam';
  Rec.Nazwisko := 'Boduch';
  Rec.Kod := 54150;

  ShowMessage(Rec.Imie);

Na samym początku deklarowana jest zmienna wskazująca na utworzony rekord. Następnie po słowie "Begin" do tego rekordu przypisywane są dane. Teraz połączenie rekordu z tablicą:

procedure TForm1.Button1Click(Sender: TObject);
type
  TRecord = record
    Imie : String;
    Nazwisko: String;
  end;

const
  Tablica : array[0..1] of TRecord =
  ((Imie: 'Adam'; Nazwisko: 'Boduch'),
  (Imie: 'James'; Nazwisko: 'Bond'));
begin
  ShowMessage(
  Tablica[0].Imie + ' ma na nazwisko: ' + Tablica[0].Nazwisko + #13+
  Tablica[1].Imie + ' ma na nazwisko: ' + Tablica[1].Nazwisko
  );

end;

Tym razem rekord nie został zadeklarowany w sekcji "Interface", lecz w obrębie procedury. Można i tak, ale w takim wypadku, gdy z innych procedur będziesz się próbował odwołać do tego rekordu to "wyskoczy" Ci błąd - kompilator nie będzie wiedział, co to jest "TRecord". Następnie deklarowana zostaje stała, która wskazuje na rekord! Jeżeli tablica zadeklarowana jest jako stała to w tej stałej trzeba ja wypełnić. Jak widzisz odbywa się to w sposób charakterystyczny i trzeba się po prostu tego nauczyć. Aha - znak #13 - oznacza on znak ENTER. Jest to tzw. znak ASCII, który oznacza znak Entera - czyli te dwie linie będą od siebie oddzielone. Możliwe jest zastosowanie podwójnego znaku entera: #13#13.
Być może nie była to ciekawa cześć rozdziału, ale wymagana, aby przejść dalej. Zapewniam się, że z czasem połapiesz się, o co chodzi :)

Grafika

Tym razem zaprezentuje Wam program - będzie to program, który ustawia kolor i kształty, a następnie wyświetla je na ekranie. Zacznijmy jego budowę.
Budowanie szkieletu:
1. Przede wszystkim umieść na formie Panel i zmień jego właściwość "Align" na "alRight" - spowoduje to umieszczenie Panelu po prawej stronie. Usuń właściwość "Caption" panelu. Zmień w Inspektorze Obiektów właściwość "ParentColor" na False. Jeżeli ta właściwość wynosi "True" to kolor Panelu będzie taki sam jak kolor formy.
2. Zmień kolor formy na biały ( właściwość "Color" :))
3. Na Panelu umieść komponent "RadioGroup" ( paleta: Standard ). Zmień jego właściwość "Name" na "Shape". Teraz mając zaznaczony ten komponent kliknij w Inspektorze Obiektów na właściwość "Items". Otworzy się okienko, w którym wpisz tekst:

prostokąt
elipsa
wycinek koła
łamana
prostokąt zaokrąglony
wielokąt
odcinek

  Zawierć to przyciskiem OK. Teraz w komponencie pojawił się tekst, który wpisałeś. Właśnie do tego służy ten komponent. Dzięki niemu będzie można zaznaczyć opcje, która nas interesuje - czyli zadecydować, jaki kształt ma się pojawić na formie.
4. Na tym samym Panelu poniżej umieść komponent "GroupBox" - zmień jego nazwę na "Setup".
5. Co teraz? Na tym "GroupBox'ie" musisz umieścić parę komponentów symbolizujących ustawienia pędzla i wypełnienia. Ja umieściłem takie komponenty:
Komponent Panel (Name: PColorLine ). Ten komponent ma symbolizować kolor linii. Oczywiście zmniejsz rozmiary tego panelu oraz zmień jego kolor na czarny.
Komponent "TSpinEdit" [paleta: Win 3.1 ] (Name: LineSize ). Ten komponet ma określać grubość linii. Zmień jego właściwość "MaxValue" na 10, a "MinValue" na 1; "Value" na 1.
Komponent "TComboBox" (Name: PStyle ). Ma on określać styl linii. W "Items" tegoż komponentu wpisz: (jeden pod drugim! ): psDash, psDashDot, psDashDotDot, psDot,    psInsideFrame, psSolid
Komponent "Panel" (Name: "BrushColor" ). Służy do określenia koloru wypełnienia.
Komponent "ComboBox" (Name: "Style" ). Określa styl wypełnienia. Kliknij na "Items" i wpisz taki tekst: bsSolid, bsCross, bsDiagCross, bsHorizontal, bsVertical,
bsFDiagonal, bsBDiagonal

Uff.... Jeszcze dwa komponenty typu "TColorDialog" (paleta: Dialogs ). Nazwij je odpowiednio "BrushColor" i "LineColor". Teraz pozostało wpisanie kodu. Kliknij dwukrotnie na komponencie "Shapes" - wygenerujesz procedurę "OnClick" komponentu. Wpisz taką treść:

procedure TMainForm.ShapeClick(Sender: TObject);
{ Stała ta zawiera wpolrzedne punktow. Wymagane, aby wyswietlic
  wycinek kola }
const
  Wielokat: array[0..3] of TPoint =
  ((X: 0; Y:0), (X: 150; Y:50), (X:230; Y:130), (X:40; Y:120));
var
  R : TRect;
begin
  R := ClientRect; //obszar formy
{ do obszaru odejmij szerokosc Panelu }
  R := Rect(R.Left, R.Top, R.Right - Panel1.Width, R.Bottom);

{ W zaleznosci od wybranej opcji na komponencie "TRadioButton" wykonywane
  sa odpowiednie funkcje. }

  case Shape.ItemIndex of
    0: begin
         Repaint; // odswiez obraz
         Ustaw(Sender); // wykonaj procedure
         Canvas.Rectangle(20, 20, 220, 220); // prostokat
       end;
    1: begin
         Repaint;
         Ustaw(Sender);
         Canvas.Ellipse(R); // elipsa
       end;
    2: begin
         Repaint;
         Ustaw(Sender); // wycinek kola
         Canvas.Pie(0, 0, ClientWidth - Panel1.Width, ClientHeight, 90, 0, 300, 10);
       end;
    3: begin
         Repaint;
         Ustaw(Sender);
       with ClientRect do  // łamana
         Canvas.Arc(Left, Top, Right - Panel1.Width, Bottom, Right, Top, Left, Top);
       end;
    4: begin
         Repaint;
         Ustaw(Sender);
         Canvas.RoundRect(20, 20, 220, 220, 30, 30); // prostokad z zaokraglonymi naroznikami
       end;
    5: begin
         Repaint;
         Ustaw(Sender);
         Canvas.Polygon(Wielokat); // wielokat
       end;
    6: begin
         Repaint;
         Ustaw(Sender);
       with ClientRect do  // odcinek
         Canvas.Chord(Left, Top, Right - Panel1.Width, Bottom, Right, Top, Left, Top);
       end;
  end;
end;


Cóż tutaj nastąpiło zastosowanie instrukcji case. Na samym początku deklaracja tablicy typu Tpoint. W poprzednim rozdziale poznałeś budowę tego typu. Tablica ta określa współrzędne punktów, które będą nam później potrzebne. Właściwość "ItemIndex" komponentu określa zaznaczenie pozycji w komponencie ( a konkretniej numer zaznaczonej pozycji ). Następnie zmienna typu "TRect". Co ona właściwie określa? Otóż zawiera ona pozycje Left, Top, Right i Bottom, czyli lewą, prawą, dolną i górną. Do zmiennej "R" zostanie przypisana funkcja, „ClientRect", która zawiera wymiary formularza. Czyli np. R.Left to lewa pozycja formy. Ale przecież na formie położony jest komponent "Panel". Trzeba, więc odjąć jego szerokość od zmiennej "R", a konkretnie od "R.Right", która określa szerokość ( prawą pozycje ) formy.
Dobra dalej następuje rysowanie odpowiednich figur w zależności od wybranej opcji. Najpierw polecenie "Repaint" - wyczyszczenie formularza, a następnie wywołanie procedury "Ustaw". Zaraz, zaraz, przecież nie napisaliśmy żadnej procedury "Ustaw"! Trzeba to nadrobić. W sekcji "private" dodaj taką linie:

  procedure Ustaw(Sender: TObject);

Uzupełnij teraz tę procedurę w sekcji "Implementation":

procedure TMainForm.Ustaw(Sender: TObject);
begin
// Ustaw styl wypelnienia w zaleznosci od wybranego stylu w kontrolce
  Canvas.Brush.Style := BrushStyle[Style.ItemIndex];
// kolor wypelniania w zaleznosci od koloru Panela
  Canvas.Brush.Color := PBrushColor.Color;
// Ustaw styl pedzla w zaleznosci od opcji wybranej w kontrolce
  Canvas.Pen.Style := PenStyle[PStyle.itemIndex];
// kolor pedzla w zaleznosci od koloru panelu
  Canvas.Pen.Color := PColorLine.Color;
// Ustaw szerkosc pedzla w zaleznosci od wybranej opcji w kontrolce
  Canvas.Pen.Width := LineSize.Value;
end;

Procedura ta ustawia właściwości pędzla i wypełnienia na podst. ustawień komponentów. "BrushStyle" to tablica, która zadeklarowaliśmy. Trzeba przecież podać parametr tablicy. Parametrem będzie właściwość "ItemIndex" komponentu "Style", która to zawiera różne style. Jeszcze pozostało napisać dwie procedury obsługujące klikniecie na Panelu "PColorLine", "PBrushColor". Przedstawione są one na poniższym listingu:


(**************************************************)
(*      Canvas Test programme for Delphi 5      *)
(*      Copyright (c) 2001 by Adam Boduch        *)
(*          Service for programmers              *)
(*      HTTP://WWW.PROGRAMOWANIR.OF.PL          *)
(*      E-mail:  boduch@poland.com                *)
(**************************************************)
// Program prezentuje użycie funkcji VCL Canvas.
// Prezentuje on użycie rysowania figur itp.
// Jest to przykład do kursu:
//    "Delphi5 dla początkujących"
//  http://www.programowanie.of.pl

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Spin;

{ Stale oznaczajace odpowiednio style wypelnienia (TBrushStyle) oraz
  styl pedzla. }

const
  BrushStyle : array[0..6] of TBrushStyle =
  (bsSolid, bsCross, bsDiagCross, bsHorizontal, bsVertical, bsFDiagonal,
   bsBDiagonal);
  PenStyle : array[0..5] of TPenStyle =
  (psDash, psDashDot, psDashDotDot, psDot, psInsideFrame, psSolid);


type
  TMainForm = class(TForm)
    Panel1: TPanel;
    Shape: TRadioGroup;
    Setup: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    LineSize: TSpinEdit;
    Style: TComboBox;
    PColorLine: TPanel;
    PBrushColor: TPanel;
    LineColor: TColorDialog;
    BrushColor: TColorDialog;
    Label5: TLabel;
    PStyle: TComboBox;
    procedure ShapeClick(Sender: TObject);
    procedure PColorLineClick(Sender: TObject);
    procedure PBrushColorClick(Sender: TObject);
  private
{ Procedura ustawiająca właściwości pędzla oraz wypełniania }
     procedure Ustaw(Sender: TObject);
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

procedure TMainForm.ShapeClick(Sender: TObject);
{ Stała ta zawiera współrzędne punktów. Wymagane, aby wyświetlić
  wycinek koła }
const
  Wielokat: array[0..3] of TPoint =
  ((X: 0; Y:0), (X: 150; Y:50), (X:230; Y:130), (X:40; Y:120));
var
  R : TRect;
begin
  R := ClientRect; //obszar formy
{ do obszaru odejmij szerokość Panelu }
  R := Rect(R.Left, R.Top, R.Right - Panel1.Width, R.Bottom);

{ W zaleznosci od wybranej opcji na komponencie "TRadioButton" wykonywane
  sa odpowiednie funkcje. }

  case Shape.ItemIndex of
    0: begin
         Repaint; // odswiez obraz
         Ustaw(Sender); // wykonaj procedure
         Canvas.Rectangle(20, 20, 220, 220); // prostokat
       end;
    1: begin
         Repaint;
         Ustaw(Sender);
         Canvas.Ellipse(R); // elipsa
       end;
    2: begin
         Repaint;
         Ustaw(Sender); // wycinek kola
         Canvas.Pie(0, 0, ClientWidth - Panel1.Width, ClientHeight, 90, 0, 300, 10);
       end;
    3: begin
         Repaint;
         Ustaw(Sender);
       with ClientRect do  // łamana  [ dziala tylko wtedy, gdy Pen.Style := psSolid ]
         Canvas.Arc(Left, Top, Right - Panel1.Width, Bottom, Right, Top, Left, Top);
       end;
    4: begin
         Repaint;
         Ustaw(Sender);
         Canvas.RoundRect(20, 20, 220, 220, 30, 30); // prostokad z zaokraglonymi naroznikami
       end;
    5: begin
         Repaint;
         Ustaw(Sender);
         Canvas.Polygon(Wielokat); // wielokat
       end;
    6: begin
         Repaint;
         Ustaw(Sender);
       with ClientRect do  // odcinek
         Canvas.Chord(Left, Top, Right - Panel1.Width, Bottom, Right, Top, Left, Top);
       end;
  end;
end;

procedure TMainForm.Ustaw(Sender: TObject);
begin
// Ustaw styl wypelnienia w zaleznosci od wybranego stylu w kontrolce
  Canvas.Brush.Style := BrushStyle[Style.ItemIndex];
// kolor wypelniania w zaleznosci od koloru Panela
  Canvas.Brush.Color := PBrushColor.Color;
// Ustaw styl pedzla w zaleznosci od opcji wybranej w kontrolce
  Canvas.Pen.Style := PenStyle[PStyle.itemIndex];
// kolor pedzla w zaleznosci od koloru panelu
  Canvas.Pen.Color := PColorLine.Color;
// Ustaw szerkosc pedzla w zaleznosci od wybranej opcji w kontrolce
  Canvas.Pen.Width := LineSize.Value;
end;

procedure TMainForm.PColorLineClick(Sender: TObject);
begin
// wyswietla komponent i ustawia kolor Panelu w zaleznosci
// od wybranego kolru w komponencie
  if LineColor.Execute then
    PColorLine.Color := LineColor.Color;
end;

procedure TMainForm.PBrushColorClick(Sender: TObject);
begin  // j/w
  if BrushColor.Execute then
    PBrushColor.Color := BrushColor.Color;
end;

{ END }

end.


No to by było na tyle :) W następnym rozdziale jeszcze trochę grafiki i animacje! Tak, tak. Jeżeli czegoś nie rozumiecie to piszcie na mój adres. Odwiedźcie też tę stronę: http://www.programowanie.of.pl - tam znajdziecie dużo kodów źródłowych, komponentów, artykułów, FAQ-ów. Innymi słowy wszystko o programowaniu!


Adam Boduch
e-mail: boduch@poland.com
http://www.programowanie.of.pl

Poprzedni artykuł Następny artykuł


Stare Gry - chcesz pograc w gry sprzed lat?


Copyright 1999-2001 Magazyn internetowy NoName
Wszelkie prawa zastrzeżone