Krótki artykuł o PageControl

Stark

Wiele osób na forum pyta się o sprawy związane z obsługą PageControl. Postanowiłem napisać krótki artykuł przedstawiający możliwości tego komponentu.

Zacznijmy od podstaw - PageControl jest komponentem pozwalającym na tworzenie zakładek, takich jak np. palety komponentów w Delphi czy zakładki w FireFoxie. Na każdej zakładce możemy umieścić dowolne komponenty. Same zakładki tworzymy klikając prawym przyciskiem myszy na komponent i wybierając z menu opcję New Page.

Często nie będziemy chcieli tworzyć stron PageControl podczas pisania programu, tylko w razie potrzeby tworzyć i zamykać zakładki w czasie działania aplikacji. Dynamiczną stronę tworzymy tak jak wszystkie dynamiczne komponenty. Umieść na formie jeden Button i PageControl. W OnClick przycisku umieść kod:

procedure TForm1.Button1Click(Sender: TObject);
var zakladka : TTabSheet;
begin
zakladka := TTabSheet.Create(Self);
zakladka.Caption := 'Nowa zakładka';
zakladka.PageControl := PageControl1;
zakladka.Show;
end;

Objaśnienie:

zakladka := TTabSheet.Create(Self);

tworzy nową zakładkę;

zakladka.Caption := 'Nowa zakładka';

przypisuje tytuł zakładki;

zakladka.PageControl := PageControl1;

określa komponent PageControl, na którym zakładka się pojawi;

zakladka.Show;

przechodzi do utworzonej zakładki;

Aby usunąć zakładkę postępujemy następująco:

PageControl1.ActivePage.Free;

Właściwość ActivePage zwraca aktualnie pokazaną stronę, a metoda Free usuwa ją.

Teraz pomówimy o komponentach na zakładkach. Załóżmy, że piszemy prosty edytor tekstowy z wieloma zakładkami. Jak zrobić, aby po wybraniu z menu opcji Nowy plik została utworzona nowa strona z komponentem Memo? Umieść na formie komponent MainMenu i utwórz w nim opcję Nowy.

procedure TForm1.NowyClick(Sender: TObject);
var zakladka : TTabSheet;
    memo     : TMemo;
begin
zakladka := TTabSheet.Create(Self);
zakladka.Caption := 'Nowa';
zakladka.PageControl := PageControl1;

memo := TMemo.Create(Self);
memo.Align := alClient;
memo.Parent := zakladka;

zakladka.Show;
end;

Objaśnienie:

memo := TMemo.Create(Self);

tworzy komponent Memo;

memo.Align := alClient;

ustawia rozmiar Memo na całą zakładkę;

memo.Parent := zakladka;

ustala Memo na zakładce (nowa strona jest rodzicem Memo);

W porządku, mamy już tworzenie nowych elementów edytora. Użytkownik programu pisze swój tekst, następnie chce go zapisać do pliku. Aby to zrobić, użyjemy metody

Memo.Lines.SaveToFile

Jak jednak dostać się do niej nie znając nazwy komponentu Memo? Do każdego komponentu na zakładce możemy się odwołać poprzez właściwość Controls. Jeżeli mamy na stronie tylko komponent Memo wystarczy napisać:

(PageControl1.ActivePage.Controls[0] as TMemo).Lines.SaveToFile('c:\plik.txt');

Jeżeli na zakładce jest więcej komponentów musimy sprawdzić w pętli wszystkie elementy tablicy Controls i sprawdzić, czy są one typu TMemo:

with PageControl1.ActivePage do
 begin
 for i := 0 to ControlCount-1 do
  begin
  if (Controls[i] is TMemo) then (Controls[i] as TMemo).Lines.SaveToFile('c:\plik.txt');
  end;
 end;

I to by było na tyle. Mam nadzieję, że przydał się Wam mój pierwszy artykuł na 4programmers.net. Może będą następne :D.

User:Stark

17 komentarzy

OldShaterhan, sprawdź proszę swój kod, masz w kodzie kilka błędów, które chyba najczęściej występują w programowaniu...

Ja mam taką prośbę: Niech ktoś zrobi taki artykuł dostosowany dio WebBrowsera, bo u mnie częściowo nie działa, oto błędy:
[Error] Unit1.pas(49): Undeclared identifier: 'TWebBrowser'
[Error] Unit1.pas(56): Missing operator or semicolon
[Error] Unit1.pas(57): Missing operator or semicolon
[Fatal Error] Project2.dpr(5): Could not compile used unit 'Unit1.pas'

Ale PageControl1.ActivePage.Free; nie usuwa mi aktywnej zakładki, tylko ostatnią. Jak usunąć aktywną? Poza tym to art super.

@kwakwels
właśnie ja też takiego czegoś potrzebuje może ktoś wie jak takie coś zrobić
a art na 5+ :)

W Turbo Delphi 2006 nie ma wprost komponentu SpinEdit, nie da sie go wprost doinstalować, jest za to kod źródlowy.
Tworzę go więc dynamicznie w przy pomocy metody create(self). Ale nie wiem, jak mu przypisac procedurę obsługi zdarzenia onchange. Kompilator nie ma jeszcze tego komponentu.

A ktos może wie, jak umieścić na nowo stworzonej zakładce nowo stworzony Komponent WebBrowser, albo MozillaBrowser ??:/ [własciwosc parent odpada..;/]

Kto by pomyślał, że w tym komponencie, żeby zmienić opis zakładki trzeba zmienić jej Name...

U mnie to działa. Wyślij mi swój kod na priva, może coś napisałeś nie tak jak trzeba.

Dokładnie zrobiłem tak jak tutaj tylko zamiast memo dałem RichEdit i jest kapa. Utworzenie pierwszej nowej zakładki to luksus ale jak tworze nastepna to nagle RichEdit z tej poprzedniej mi znika a na tej i natsepnych juz sie nie pokazuje :(

A nie wiecie jak utworzyć zakładkę w innej formie? To jest żeby przycisk tworzył nową zakładkę nie w oknie w którym się znajduje tylko w innym oknie (już istniejącym). Proszę pomóżcie, bo jestem początkującym programistą i nie wiem jak to zrobić.

banalne, ale przydatne (sam sie kiedys nad tym meczylem, gdy dopiero zaczynalem zabawe w Delphim)

banały :P lepiej zrobic funckje GetTab i NewTab mozna tez zrobic GetMemo. tak czy inaczej nawet niezle wyszlo ;p

Może zakładka jest właścicielem Image'a i próbujesz zwolnić komponent już po jego zwolnieniu przez właściciela. Spróbuj odwrócić kolejność - destrukcja Image'a i dopiero potem karty PageControl.

problemy moga pojawic sie gdy chesz zamknac zkladke poprzez dynamiczny komponent utworzony na dynamicznie stworzonej zakladce, np. TImage z powiedzmy obrazkiem krzyzyka(taki niby krzyzyk zamykania jak w kazdym oknie), w zdarzeniu OnClick chcialem usunac zakladke a takze dynamiczny TImage, pojawial sie Acces violation zwiazany z usuwaniem samego siebie TImage