Okna w Delphi/Lazarus

0

Witam.
Programowałem dotąd w C/C#/Java, postanowiłem teraz dzięki projektowi Lazarus przyjrzeć się językowi Delphi.
Zacząłem zabawę z oknami. Otóż w oknie głównym zadeklarowałem sobie inne okno, które wywołuję z przycisku:

var
  oknoGlowne: ToknoGlowne;
  oDArtyste: ToknoDodajArtyste;  

A tutaj kod przycisku:

procedure ToknoGlowne.tbDodajClick(Sender: TObject);
begin
  oDArtyste:= ToknoDodajArtyste.Create(nil);
  oDArtyste.Show;
end;  

Okno oDArtyste poprawnie się wywołuje. Mam tam też przycisk do zamknięcia tego okna. Niestety, jego kod nie chce go już zamknąć:

procedure ToknoDodajArtyste.btnAnulujClick(Sender: TObject);
begin
  oknoDodajArtyste.Close;
end; 

Co takiego robię źle?

0

Jakiś błąd, nie zamyka się?

0

Po prostu się nie zamyka.

0

W formie nr 2 napisz tak:

procedure ToknoDodajArtyste.btnAnulujClick(Sender: TObject);
begin
  Self.Close;
end;

Dlaczego?
Bo:
a) w pierwszej formie niepotrzebnie tworzysz dodatkowy obiekt formy (zwykle robi się sam)
b) a w formie docelowej odwołujesz się właśnie do tego obiektu automatycznie stworzonego (czyli de facto masz dwie formy dodajArtystę jednocześnie)
c) dlatego najbezpieczniej w obsłudze zdarzeń odwoływać się do aktualnej formy przez "Self"

Gdybyś szukał gdzie automatycznie tworzą się formy to znajdziesz to komendą:
Projekt \ Pokaż źródło

Przy większych projektach się to wyłącza, bo zamula program (formy tworzy się wtedy ręcznie - tak jak to zrobiłeś w ToknoGlowne.tbDodajClick).

0

Dzięki, już próbuję rozwiązania. Właśnie szukałem czegoś w stylu słowa this z języków c-podobnych.

EDYCJA:

Działa!

Co do pkt a. Nie powinienem używać forma:= Tforma.create();?

0

Przy dużych projektach - tak.
W Delphi / Lazarus masz dwa tryby tworzenia form:
a) automatycznie - w kodzie projektu (w Lazarus patrz "Projekt \ Pokaż źródło")
b) ręcznie - tak jak to napisałeś w ToknoGlowne.tbDodajClick

Jeśli chodzi o (b) to jest to bardziej polecana forma dla większych projektów.
Ale nawet wtedy polecałbym raczej przechowywać uchwyt / wskaźnik do formy jako atrybut formy wywołującej (żeby był schowany i powiązany z obiektem wywołującym) lub używać uchwytu automatycznie tworzonego (oknoDodajArtyste).

W przypadku (b) powinieneś zakomentować / usunąć automatyczne tworzenie w kodzie projektu.

  Application.Initialize;
  Application.CreateForm(ToknoGlowne, oknoGlowne);
  //Application.CreateForm(ToknoDodajArtyste, oknoDodajArtyste);
  Application.Run;
0

Wszystko działa. Dzięki za informacje. Jak coś, to będę pytał :)

0

Witam, kontynuuję pracę nad moim programem. Napotkałem kolejną przeszkodę. Zaprojektowałem sobie moduł odpowiedzialny za odczyt i zapis do plików elementowych mojego rekordu. Niestety, podczas odczytu dzieje się dziwna rzecz: Nazwa artysty (w kodzie poniżej) nie pokazuje się w listbox (zostaje dodanynowy wpis jak przy normalnym add, ale pusty), a po zamknięciu okna głównego otrzymuję błąd: Project xaudio.app raised exception class 'External: EXC_BAD_ACCESS'.

Oto poszczególne kody:

Wywołanie odczytu, dodawanie elementów

procedure TOkno_glowne.FormShow(Sender: TObject);
var
  i: integer;
  max: integer;
  art: TArtysta;
begin
  max:= xaobj.pobierz_liczbe_art();
  //Pobieranie i wyswietlanie danych
  if max <> -1 then //Plik istnieje
  begin
   for i:= 0 to max - 1 do
   begin
    art:= xaobj.pobierz_art(i);
    ListBoxArtysci.Items.Add(art.nazwa);
   end;
  end;

end;                                   

Definicja xaobj.pobierz_liczbe_art();

{ Zwraca liczbe elementow w pliku artystow
-1 zwrocone, kiedy plik artystow nie istnieje }
function pobierz_liczbe_art(): integer;
var
  liczba: integer;
begin
  if FileExists(sciezka_art) then
  begin
   Assign(p_artysci, sciezka_art);
   Reset(p_artysci);
   liczba:= FileSize(p_artysci);
   Close(p_artysci);
   pobierz_liczbe_art:= liczba;
  end
  else pobierz_liczbe_art:= -1;
end; 

Oraz funkcja pobierająca samego artystę z pliku:

//Zwraca artyste o wybranym indeksie
function pobierz_art(ind: integer): TArtysta;
var
  art: TArtysta;
begin
  Assign(p_artysci, sciezka_art);
  Reset(p_artysci);
  Seek(p_artysci, ind);
  Read(p_artysci, art);
  Close(p_artysci);
  pobierz_art:=art;
end;   
0

Pokaż definicję typu TArtysta, ale zakładam że nie ma tam niespodzianek. Na pierwszy rzut oka nic złego się tu nie dzieje.

0

a po zamknięciu okna głównego otrzymuję błąd: Project xaudio.app raised exception class 'External: EXC_BAD_ACCESS'.

Naucz się debuggera używać, i inna sprawa - nowy temat. Ale czy jest ktoś kto jeszcze mnie tutaj słucha? Nie.

0

Wedle życzenia: Z każdym innym problemem będzie nowy temat.
Tutaj definicja TArtysty:

type
  //Definicja artysty
  TArtysta = record
   nazwa: string;
   rok_rozp: string;
   rok_zak: string;
  end;

Przy czym z zapisem nie ma on problemu, a w podobnej aplikacji konsolowej też nie miałem spacjalnie problemów z odczytem.

W kwestii debuggera: O ile w Visual Studio jego używanie było dla mnie banalnie proste, to w Lazarusie nie umiem go rozgryźć, a Twórcy IDE chyba za wszelką cenę starają się ukryć informacje o tym jak go używać/podglądać zawartość zmiennych/pól.

0

Problem na pewno jest w tym, że chcesz zapisać typy string bez podawania ich długości. Trzeba je ograniczyć w ilości znaków albo zapisać wcześniej ilośc tych znaków. Przeanalizuj sobie poniższe kody, a wszystko powinno być jasne. Wprawdzie aplikacja konsolowa, ale to pisane na szybko żeby tylko pomóc zrozumieć ideę działania zapisu oraz odczytu danych.

Przykład pierwszy:

program example1;

{$APPTYPE CONSOLE}

type
  TRec = record
    Cnt : Byte;
    Txt : string[20];
  end;
const
  AFileName = 'D:\test.bin';
  TxtArr : array[1..2] of string = ('raz', 'dwa');
var
  I : integer;
  AFile : file of TRec;
  DataArr : array[1..2] of TRec;
begin
  for I := Low(DataArr) to High(DataArr) do
  begin
    with DataArr[I] do
    begin
      Cnt := I;
      Txt := TxtArr[I];
    end;
  end;
  // Zapis
  Assign(AFile, AFileName);
  Rewrite(AFile);
  for I := Low(DataArr) to High(DataArr) do
    Write(AFile, DataArr[I]);
  Close(AFile);
  // Odczyt
  Assign(AFile, AFileName);
  Reset(AFile);
  for I := Low(DataArr) to High(DataArr) do
  begin
    Writeln('Rekord numer: ', I);
    with DataArr[I] do
    begin
      Writeln('Pole Cnt: ', I);
      Writeln('Pole Txt: ', Txt);
    end;
  end;
  Writeln('Rozmiar pliku (ilosc rekordow): ', FileSize(AFile));
  Close(AFile);
  Readln;
end.

Przykład drugi:

program example2;

{$APPTYPE CONSOLE}

const
  MaxCnt = 6;
  AFileName = 'D:\test_2.bin';
  TxtArr : array[1..MaxCnt] of string = ('ucz', 'sie', 'podstaw', 'i', 'kombinuj', 'sam.');
var
  S : string;
  AFile : File of Byte;
  I, TxtLength, RecCnt : integer;
  DataArr : array[1..MaxCnt] of string;
begin
  for I := Low(DataArr) to High(DataArr) do
    DataArr[I] := TxtArr[I];
  // Zapis
  RecCnt := Length(DataArr);
  Assign(AFile, AFileName);
  Rewrite(AFile);
  BLockWrite(AFile, RecCnt, SizeOf(RecCnt));
  for I := Low(DataArr) to High(DataArr) do
  begin
    TxtLength := Length(DataArr[I]);
    BlockWrite(AFile, TxtLength, SizeOf(TxtLength));
    BlockWrite(AFile, DataArr[I][1], TxtLength);
  end;
  Close(AFile);
  // Odczyt
  Assign(AFile, AFileName);
  Reset(AFile);
  BlockRead(AFile, RecCnt, SizeOf(RecCnt));
  for I := 1 to RecCnt do
  begin
    BlockRead(AFile, TxtLength, SizeOf(TxtLength));
    SetLength(S, TxtLength);
    BlockRead(AFile, S[1], TxtLength);
    Writeln(S);
  end;
  Close(AFile);
  Readln;
end.
0

Zdefiniowanie długości stringów pomogło :) Dzięki za informacje! :)

0

to w Lazarusie nie umiem go rozgryźć, a Twórcy IDE chyba za wszelką cenę starają się ukryć informacje o tym jak go używać/podglądać zawartość zmiennych/pól.

Debugger w Lazarusie jest domyślnie włączony, jeżeli tylko w opcjach projektu/kompilatora wybierzesz nie usuwanie symboli z pliku oraz debuger (który domyślnie jest zazwyczaj wybrany).
Pokombinuj trochę z opcjami, ale upewnij się że debugger nie działa, gdy masz błąd daj RAlt+S - Powinno wyświetlić call stack... Jak lista jest pusta to coś jest na rzeczy (ja bym się domyślał że debugger wyłaczony w opcjach), jeśli na liście nie ma numerów linii kodu albo są same adresy to wybrałeś zły poziom debuggowania w opcjach...

Popatrz sobie jeszce na:
http://wiki.lazarus.freepascal.org/GDB_Debugger_Tips
http://wiki.lazarus.freepascal.org/Lazarus_Faq#Debugger

1 użytkowników online, w tym zalogowanych: 0, gości: 1