7.Prednaska

Z Pascal
Revízia z 14:55, 8. október 2012; Andrej (Diskusia | príspevky)

(rozdiel) ← Staršia verzia | Aktuálna úprava (rozdiel) | Novšia verzia → (rozdiel)
Prejsť na: navigácia, hľadanie
7. Prednáška

úlohy | cvičenie


Udalosti

Tento princíp sa používa v oknových grafických rozhraniach (GUI), napr. keď sa programuje vo Windows. Je to špeciálny spôsob riadenia programov, v ktorom aplikácia, formulár aj samotné komponenty môžu reagovať na nejaké podnety (väčšinou) z vonku. Hovoríme im udalosti a udalosťami riadené programovanie(po angl. event).

Každá udalosť má

  • meno, napr. onClick, onCreate
  • akciu, t.j. časť programu, ktorá sa vykoná pri vzniku udalosti;
    • najčastejšie sa realizujú procedúrami, napr. Button1Click, FormCreate
  • mená procedúr sa vytvárajú automaticky (mohli by sme ich aj zmeniť) v inšpektore objektov, pričom sa poskladá meno komponentu a meno udalosti
  • akcie mávajú aj parametre (špecifický detail), ktorý nám niekedy upresní, za akých okolností sa udalosť udiala


Práca s myšou

V Lazaruse sa s myšou pracuje pomocou udalostí, ktoré automaticky vznikajú pri každom pohybe myši alebo klikaní do formulára. Túto udalosť dostáva ten komponent formulára, nad ktorým sa myš práve nachádza (napr. grafická plocha alebo tlačidlo). Procedúra, ktorá sa vyvolá ako reakcia na udalosť (event driver) pohybu alebo kliknutia myši, dostáva ako parametre aj súradnice myši (X, Y) - tieto sú vždy relatívne vzhľadom na ľavý horný roh komponentu - v grafickej ploche sú to normálne grafické súradnice bodu.


Klikanie


Začneme s udalosťou OnMouseDown, ktorá označuje, že myšou sme klikli niekde do grafickej plochy. Takže v Inšpektore objektov v záložke Udalosti nájdeme riadok OnMouseDown a potom sem dvojklikneme:

v inšpektore prejdeme na záložku Udalosti nájdeme riadok onMouseDown dvojklikneme

Otestujeme to programom, v ktorom kliknutie do grafickej plochy na tomto mieste nakreslí malý kruh a vypíše súradnice kliknutého bodu. Nesmiene zabudnúť vo FormCreate vymazať grafickú plochu:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Image1.Canvas.Ellipse(X - 4, Y - 4, X + 4, Y + 4);
  Image1.Canvas.TextOut(X, Y, Format('[%d, %d]', [X, Y]));
end;

klikanie do plochy

Všimnite si, že procedúra Image1MouseDown má viac rôznych parametrov. Pre nás sú najdôležitejšie dva parametre X a Y, v ktorých dostávame súradnice kliknutého miesta v grafickej ploche.

Nasledujúci program ukáže, že kliknuté body môžeme veľmi jednoducho spájať čiarami (LineTo). V každom kliknutom bode nakreslíme aj malú kružnicu, aby bolo lepšie vidieť kliknuté miesto:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Image1.Canvas.LineTo(X, Y);
  Image1.Canvas.Ellipse(X - 2, Y - 2, X + 2, Y + 2);
end;

spájanie kliknutých bodov

Ďalší program ukazuje spôsob, ako pracujeme s klikaním do štvorčekov štvorcovej siete. Procedúra FormCreate nakreslí prázdnu štvorcovú sieť. Potom každé kliknutie do plochy zistí, do ktorého štvorčeka sme klikli a ten potom vyfarbí modrou farbou. V programe sme definovali pomocnú globálnu procedúru Stvorcek, ktorá nakreslí štvorček v R-tom riadku a S-tom stĺpci štvorcovej siete. Globálna konštanta D má hodnotu veľkosti štvorčeka siete.

const
  D = 50;
procedure Stvorcek(R, S: Integer);
begin
  Form1.Image1.Canvas.Rectangle(S * D, R * D, S * D + D + 1, R * D + D + 1);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
  I, J: Integer;
begin
  for I := 0 to Image1.Height div D do
    for J := 0 to Image1.Width div D do
      Stvorcek(I, J);
  Image1.Canvas.Brush.Color := clBlue;
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Stvorcek(Y div D, X div D);
end;

klikanie do štvorcovej siete

Pri kliknutí do plochy vypočítame riadok (Y div D) a stĺpec (X div D) štvorčeka siete a ten potom nakreslíme s modrou výplňou.


Pohyb myši


Ďalšou udalosťou pri práci s myšou v grafickej ploche je pohyb myši - vzniká vtedy, keď sa kurzor myši pohne nad grafickou plochou bez ohľadu na to, či je niektoré tlačidlo myši zatlačené alebo nie. V Inšpektore objektov v záložke Udalosti nájdeme riadok OnMouseMove a vytvoríme procedúru na spracovanie udalosti Image1MouseMove. Procedúra je podobná Image1MouseDown - tiež má dva parametre X a Y, ktoré sú momentálne súradnice myši nad plochou. V nasledujúcom programe prechádzame myšou nad grafickou plochou - nemusíme pritom zatláčať tlačidlá myši:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  Image1.Canvas.Ellipse(X - 5, Y - 5, X + 5, Y + 5);
end;

200px link=http://pascal.input.sk/images/9/97/P7.x.png

Procedúra Image1MouseMove má ešte jeden užitočný parameter: Shift. V ňom nám systém odovzdáva informáciu o stlačených tlačidlách myši. Tento parameter je množinového typu a s pascalovskými množinami zatiaľ pracovať nevieme. Tento parameter môže nadobúdať rôzne hodnoty, ale pre nás sú asi najzaujímavejšie tieto:

Shift = [] // nezatlačili sme žiadne tlačidlo
Shift = [ssLeft] // zatlačili sme len ľavé tlačidlo
Shift = [ssRight] // zatlačili sme len pravé tlačidlo
Shift = [ssLeft, ssRight] // zatlačili sme naraz obe tlačidlá

Ak chceme opraviť náš program, aby kreslil iba pri zatlačenom ľavom tlačidle, zapíšeme podmienku takto:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  if Shift = [ssLeft] then
    Image1.Canvas.Ellipse(X - 5, Y - 5, X + 5, Y + 5);
end;

200px link=http://pascal.input.sk/images/9/97/P7.x.png

Po spustení vidíme, že krúžky sa kreslia len pri zatlačenom ľavom tlačidle myši.

Ďalší program spája body na pozícii myši s nejakým dopredu zvoleným bodom (napr. 150, 150):

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  if Shift = [ssLeft] then
  begin
    Image1.Canvas.MoveTo(150, 150);
    Image1.Canvas.LineTo(X, Y);
  end;
end;

{{{3}}}

V mnohých aplikáciách, kde je dôležité poznať súradnice polohy myši, sa do Image1MouseMove pridáva výpis súradníc X a Y. Môžeme napr. pri pohybe myši vypisovať X a Y do titulku formulára (hoci by sme aj mohli niekde do formulára vložiť komponent jednoduchý text (TLabel) a súradnice myši vypisovať sem):

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  Caption := IntToStr(X) + ',' + IntToStr(Y);
  ...
end;

Súradnice myši sa teraz budú vypisovať vždy, bez ohľadu na to, čo robí program.


Ťahanie



Môžeme využiť obe udalosti od myši v jednom programe. Budeme rozlišovať kliknutie a ťahanie, pričom pri kliknutí (udalosť onMouseDown) sa niečo nastaví a pri ťahaní (udalosť onMouseMove) sa to využije. Príklad ukáže kreslenie krivky: kliknutie sem prenesie pozíciu pera (MoveTo) a ťahanie už kreslí čiary (LineTo):

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Image1.Canvas.MoveTo(X, Y);
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  if Shift = [ssLeft] then
    Image1.Canvas.LineTo(X, Y);
end;

kreslenie rukou do grafickej plochy

Pri každom kliknutí môžeme nastaviť aj hrúbku alebo farbu kreslených čiar, napr. náhodné farby a hrúbky:

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Image1.Canvas.MoveTo(X, Y);
  Image1.Canvas.Pen.Color := Random(256 * 256 * 256);
  Image1.Canvas.Pen.Width := Random(20) + 1;
end;

kreslenie s náhodnou zmenou farby a hrúbky

Pri kliknutí (onMouseDown) si môžeme v globálnych premenných napr. X1, Y1 zapamätať súradnice tohto kliknutého miesta a pri ťahaní myši (onMouseMove) môžeme túto súradnicu využiť. Napríklad nakreslíme rôznofarebné vejáre:

var
  X1, Y1: Integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  X1 := X;
  Y1 := Y;
  Image1.Canvas.Pen.Color := Random(256 * 256 * 256);
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  if Shift = [ssLeft] then
    Image1.Canvas.Line(X1, Y1, X, Y);
end;

farebné vejáre

V ďalšom programe budeme kresliť kruhy tak, že kliknutie určí stred kruhu a ťahanie určuje bod na kružnici. Aby sme mohli takúto kružnicu nakresliť, musíme vypočítať jej polomer (vzdialenosť bodu na kružnici od jej stredu).

var
  X1, Y1: Integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  X1 := X;
  Y1 := Y;
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  R: Integer;
begin
  if Shift = [ssLeft] then
  begin
    R := Round(Sqrt(Sqr(X - X1) + Sqr(Y - Y1)));
    Image1.Canvas.Ellipse(X1 - R, Y1 - R, X1 + R, Y1 + R);
  end;
end;

kreslenie kruhu ťahaním

Nasledujúci príklad ilustruje iné využitie výpočtu vzdialenosti dvoch bodov. Počas ťahania chceme kresliť náhrdelníky zložené z kruhov s polomerom napr. 20. Ak by sme pri ťahaní (onMouseMove) kreslili takéto kruhy, mohli by byť príliš nahusto a prekrývali by sa. Preto pre každý bod zistíme, či už je dostatočne vzdialený od predchádzajúceho (vzdialenosť aspoň 40) a ak áno, tak ho nakreslíme:

var
  X1, Y1: Integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  X1 := X;
  Y1 := Y;
  Image1.Canvas.Brush.Color := Random(256 * 256 * 256);
  Image1.Canvas.Ellipse(X - 10, Y - 10, X + 10, Y + 10);
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  if (Shift = [ssLeft]) and (Sqrt(Sqr(X - X1) + Sqr(Y - Y1)) >= 20) then
  begin
    Image1.Canvas.Ellipse(X - 10, Y - 10, X + 10, Y + 10);
    X1 := X;
    Y1 := Y;
  end;
end;

kreslenie kruhov nie príliš husto

Predtým sme už klikali do políčok štvorcovej siete a zafarbovali sme ich. Podobnú ideu použijeme aj v nasledujúcom programe. Pri ťahaní myšou sa budú zafarbovať krúžky, ktoré sú vo vnútri štvorcovej siete. Kliknutie nastaví náhodnú farbu.

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Image1.Canvas.Brush.Color := Random(256 * 256 * 256);
  Image1.Canvas.Pen.Color := Image1.Canvas.Brush.Color;
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
const
  D = 15;
  procedure Kruh(R, S: Integer);  // riadok a stĺpec siete
  begin
    Image1.Canvas.Ellipse(D * S, D * R, D * S + D, D * R + D);
  end;
begin
  if Shift = [ssLeft] then
    Kruh(Y div D, X div D);
end;

kruhy v štvorcovej sieti

Konštanta D označuje veľkosť štvorčeka siete, teda priemer krúžku.



späť | ďalej