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
|