Ĺadny brzuch
Hello,
Today... - dobra piszę po polsku :)
Jak wiadomo dzień bez bug'a to dzień stracony dlatego jak zwykle jakiś się znalazł. Dzisiaj okazało się, że jest potrzebny mi jest wątek, który jest wykonywany w dynamicznie tworzonej formie - i tutaj właśnie jest problem, ponieważ kiedy próbuję się odwołać z wątku do jakiego komponentu na formie to wywala mi błąd (coś tam, że nie można odczytać czegoś z jakiegoś adresu ;) )
Pytanie: jak z wątku wykonywanego w dynamicznie tworzonej formie dostać się do komponentu na tej właśnie formie.
Za wszelką pomoc dziękuję
PS. Nie pisać mi, żebym nie korzystał z dynamicznej formy :)
Nie wiem czy dobrze rozumuje (proszę bez loli i bluzg jeśli myślę w odwrotnym kierunku!), ale może do klasy wątku dodaj pole typu tego komponentu. Np:
guzik: TButton;
i zrób konstruktor tej klasy, np tak:
constructor Create(guz: TButton); override;
i uzupełnij go w ten sposób:
constructor Twatek.Create(guz: TButton); begin guzik := guz; inherited Create(False); //normalne uruchomienie wątku end;
i w wątku odwołuj się do pola klasy zamiast bezpośrednio do komponentu.
Niestety tak jak mówię, naprawdę nie wiem, czy to o to chodzi. :unsure: :unsure: :unsure:
EDIT:
chociaż po głębszym zastanowieniu dochodzę do wniosku, że to na jedno wyjdzie (jesli w ogóle zadziała).
Użytkownik programista1101 edytował ten post 27 maj 2005, 18:36
Nie takie coś nie przechodzi - nie działa nawet tworzenie dynamiczne komponentu, którego potrzebuje (w kodzie nie ma błędu, lecz na formie nie pokazuje się on :( )
Może mam zły kodzik do tworzenia form dynamicznych. Posługuję się takim
with TForm2.Create(Self) do try ShowModal; finally Free; end;
Nie używa się ShowModal przy dynamicznych formach, tylko [BShow[/B]. Najlepiej dać:Tworzenie formy: Form2:=TForm2.Create(Application); Wyświetlanie formy: Form2.Show; W OnClose dynamicznej formy: Form2.Destroy; I w OnClose pierwszej formy: Application.Terminate;
Użytkownik KSMłody edytował ten post 27 maj 2005, 20:10
KSMłody - Twój sposób nie pomógł. :(
Nie używa się ShowModal przy dynamicznych formach, tylko Show
Nie używa się czemu ?? Przecież w pomocy do Delphi jest ShowModal
-=PcSA=- a możesz gdzieś dać cały kod? Bo wtedy będzie można u siebie popróbowac, bez zbędnego zdagywania na forum.
EDIT:
//BTW przy wątkach powinno odwoływać się do innych procedur (może komponentów treż :unsure: ) poprzez Synchronioze. Odwołujesz się tak?
//BTW BTW kurcze - chyba nawijam nawinięte....
Użytkownik programista1101 edytował ten post 27 maj 2005, 20:29
Powiedz tylko czego, bo cały kod zajmuje 500 KB :)
EDIT:
//BTW przy wątkach powinno odwoływać się do innych procedur (może komponentów też ) poprzez Synchronioze. Odwołujesz się tak?
Nie wiem nawet co to jest :)
Użytkownik -=PcSA=- edytował ten post 27 maj 2005, 20:30
Przy tworzeniu wątku za pomocą repozytorium Delphi daje taki komentarz:
{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure KLASA.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
Użytkownik programista1101 edytował ten post 27 maj 2005, 20:33
Lepiej dam kodzik wątku, bo Synchronize raczej chyba nie da się w tym przypadku użyć :(
Kodzik wątku: http://arturs.aplus....c.php?p=139#139
Jakbyś chciał jeszcze jakiś kawałek kodu to daj znać to dopiszę :)
Użytkownik -=PcSA=- edytował ten post 27 maj 2005, 20:35
Nie używa się czemu ?
Ha :D Udało mi się :). Zrobiłem tak (naturalnie dla przykładu):
Po koleji:
1. Zmienne globalne na Form1:
var forma: TForm; lb: TLabel; //w przykladzie odwolamy sie do TLabel;
2. procedura tworząca komponenty:
{wszytsko dla przykładu} frm := Tform.Create(Application); lb := TLabel.Create(frm); lb.Parent := frm; lb.SetBounds(10, 10, 100, 100); lb.Caption := 'przed odwołaniem'; frm.Show; lb.onclick := go;
3. Umieszczenie procedury "go" w delaracji klasy Form1:
type TForm1 = class(TForm) {...} procedure go(sender: TObject); {...}
4. Uzupełnienie procedury GO:
procedure TForm1.go(Sender: tObject); begin TMojWatek.Create(lb); end;
5. wyglad klasy watku:
uses Classes, StdCtrls; {...} type Tmojwatek = class(TThread) myLab: TLabel; protected procedure Execute; override; public constructor Create(labelek: TLabel); procedure napis; end;
6. Uzupełnienie konstruktora:
constructor Tmojwatek.Create(labelek: TLabel); begin mylab := labelek; inherited Create(False); end;
7. Uzupełnienie procedury Execute:
procedure Tmojwatek.Execute; begin FreeOnTerminate := true; Synchronize(napis); end;
8. uzupełnienie procedury napis:
procedure Tmojwatek.napis; begin myLab.Caption := 'po odwołaniu do dynamicznego labela na dynamicznej formie z watku'; end;
Naturalnie to dla przykładu. Mam nadzieję, że po częsci udało się rozwiązać problem.
Użytkownik programista1101 edytował ten post 27 maj 2005, 21:02
Nie wiem - chyba ma pH. Niestety zrobiłem mniej więcej tak jak Ty to zrobiłeś (mniej więcej, bo chaiłem aby w Gauge coś się zmieniało) i nic nie działa - tzn. zawartość Gauge nie zmienia się - nie ma błędu ale nie zmienia się, a do tego wszystkiego nie mogę korzystać z funkcji zawartych w formie dynamicznie tworzonej :(
A jesli chodzi o ten postep. Masz tak:
for i:=-1 to IloscWpisow-1 do {....} ZamienHaslo.ProgressBar1.Position:= 1 + (i*7); //<- błąd {...} ZamienHaslo.ProgressBar1.Position:= 2 + (i*7); //<- błąd {...} ZamienHaslo.ProgressBar1.Position:= 3 + (i*7);
Przecież to logiczne, że jest błąd skoro "i" na początku jest ujemne.
EDIT:
Zrobilem u siebie też z Gauge i działa.
A jesli chcesz odwoływać się do funkcji i procedur w stworzonej formie to może dodaj parametr forma: TForm w konstruktorze oraz pole w klasie wątku? :unsure:
Użytkownik programista1101 edytował ten post 27 maj 2005, 22:10
A jesli chcesz odwoływać się do funkcji i procedur w stworzonej formie to może dodaj parametr forma: TForm w konstruktorze oraz pole w klasie wątku?
Tform w konstruktorze nie działa (chyba, że coś pomieszałem).
Co do Progress'a to się faktycznie wygłupiłem
A dodałeś do uses moduł Forms oraz pole TForm do klasy wątku? Bo u mnie działa.
BTW. Ale chyba można też wszystkie te funkcje i procedury formy dynamicznej umieścic w sekcji public dowolnej innej klasy...
Użytkownik programista1101 edytował ten post 28 maj 2005, 11:47
Pewnie, że w uses jest moduł Forms :)
BTW. Ale chyba można też wszystkie te funkcje i procedury formy dynamicznej umieścic w sekcji public dowolnej innej klasy...
Właśnie w tym rzecz, że teraz nie wiadomo dla czego kiedy wywołuję jakąś funkcję z formy dynamicznej to w funkcji podczas jej uruchomienia wywala błąd, który nie istnieje kiedy odpalę go już nie z wątku :kwasny:
Oczywiście nie muszę dodawać, że funkcje są w sekcji public
Co do pola TForm - możesz zaprezentować jakiś przykład, bo wydaje mi się, że źle robię to o czym piszesz :lol2:
Hmmm to teraz inaczej - nie używając konstruktra a wszystko dzieki sekcji public Form1. Cel: chcemy na dynamicznie stworzonej formie pokzywać postep na ProgressBar oraz w dowolnym momencie mieć możliwość odwoływania się do procedur/funkcji dla tej formy.
1. W sekcji private klasy TForm1 deklarujemy procedurę odpowiedzialną za stworzenie formy oraz komponentu.
procedure CreateComponents;
2. W sekcji public klasy TForm1 deklraujemy zmienne typu potrzebych komponentów oraz procedury/funkcje do których potem chcemy się odwoływać. Dla przykłądu jedna procedurka:
forma: TForm; Progress1: TProgressBar; procedure OnShowFormy(Sender: TObject); procedure ProceduraFormyDynamicznej;
Procedura OnShowFormy(Sender: TObject); będzie nam służyć do uruchomienia wątku i bedzie wywołana przy pojawieniu sie formy dynamicznej.
3. uzupełniamy procedurę "CreateComponents":
procedure TForm1.CreateComponents; begin forma := TForm.Create(Application); progress1 := TprogressBar.Create(forma); progress1.Parent := forma; progress1.Max := 100; progress1.SetBounds(10, 10, 300, 20); forma.OnShow := OnShowFormy; //to nie jest konieczne - mozna dac cos dowolnego tu poprostru bedzie uruchomienie watku forma.Show; end;
4. uzupełniamy procedurę "OnShowFormy"
procedure TForm1.OnShowFormy(Sender: TObject); begin TWatek.Create(False); end;
5. Uzupełniamy procedurę "ProceduraFormyDynamicznej" - przykładowo.
procedure TForm1.ProceduraFormyDynamicznej; begin if progress1.Position >= 50 then ShowMessage('To już połowa! A dokładnie: ' + IntToStr(progress1.Position); end;
6. Tworzymy nowy moduł, dodajemy go do uses (najlepiej w sekcji implementation) i wstawiamy w niego klasę wątku:
type TWatek = class(TThread) private protected procedure Execute; override; end;
7. uzupełniamy procedurę "Execute":
procedure TWatek.Execute; var i: integer; begin FreeOnTerminate := True; for i := 0 to 100 do begin Form1.Progress1.Position := i; Synchronize(Form1.ProceduraFormyDynamicznej); end; end;
Jak widać w wątku pokazujemy postęp, a także wywołujemy zdeklarowana wcześniej procedurę. W module, gdzie jest klasa wątku nalezy dodac do uses moduł z klasą TForm1.
Gdzieś w kodzie modułu z klasa TForm jeden dajemy:
CreateComponents.
Jesli to nie zadziała to ja już nie jestem w stanie pomóc.
Użytkownik programista1101 edytował ten post 28 maj 2005, 12:30
zanotowane.pl doc.pisz.pl pdf.pisz.pl zsf.htw.pl
Today... - dobra piszę po polsku :)
Jak wiadomo dzień bez bug'a to dzień stracony dlatego jak zwykle jakiś się znalazł. Dzisiaj okazało się, że jest potrzebny mi jest wątek, który jest wykonywany w dynamicznie tworzonej formie - i tutaj właśnie jest problem, ponieważ kiedy próbuję się odwołać z wątku do jakiego komponentu na formie to wywala mi błąd (coś tam, że nie można odczytać czegoś z jakiegoś adresu ;) )
Pytanie: jak z wątku wykonywanego w dynamicznie tworzonej formie dostać się do komponentu na tej właśnie formie.
Za wszelką pomoc dziękuję
PS. Nie pisać mi, żebym nie korzystał z dynamicznej formy :)
Nie wiem czy dobrze rozumuje (proszę bez loli i bluzg jeśli myślę w odwrotnym kierunku!), ale może do klasy wątku dodaj pole typu tego komponentu. Np:
guzik: TButton;
i zrób konstruktor tej klasy, np tak:
constructor Create(guz: TButton); override;
i uzupełnij go w ten sposób:
constructor Twatek.Create(guz: TButton); begin guzik := guz; inherited Create(False); //normalne uruchomienie wątku end;
i w wątku odwołuj się do pola klasy zamiast bezpośrednio do komponentu.
Niestety tak jak mówię, naprawdę nie wiem, czy to o to chodzi. :unsure: :unsure: :unsure:
EDIT:
chociaż po głębszym zastanowieniu dochodzę do wniosku, że to na jedno wyjdzie (jesli w ogóle zadziała).
Użytkownik programista1101 edytował ten post 27 maj 2005, 18:36
Nie takie coś nie przechodzi - nie działa nawet tworzenie dynamiczne komponentu, którego potrzebuje (w kodzie nie ma błędu, lecz na formie nie pokazuje się on :( )
Może mam zły kodzik do tworzenia form dynamicznych. Posługuję się takim
with TForm2.Create(Self) do try ShowModal; finally Free; end;
Nie używa się ShowModal przy dynamicznych formach, tylko [BShow[/B]. Najlepiej dać:Tworzenie formy: Form2:=TForm2.Create(Application); Wyświetlanie formy: Form2.Show; W OnClose dynamicznej formy: Form2.Destroy; I w OnClose pierwszej formy: Application.Terminate;
Użytkownik KSMłody edytował ten post 27 maj 2005, 20:10
KSMłody - Twój sposób nie pomógł. :(
Nie używa się ShowModal przy dynamicznych formach, tylko Show
Nie używa się czemu ?? Przecież w pomocy do Delphi jest ShowModal
-=PcSA=- a możesz gdzieś dać cały kod? Bo wtedy będzie można u siebie popróbowac, bez zbędnego zdagywania na forum.
EDIT:
//BTW przy wątkach powinno odwoływać się do innych procedur (może komponentów treż :unsure: ) poprzez Synchronioze. Odwołujesz się tak?
//BTW BTW kurcze - chyba nawijam nawinięte....
Użytkownik programista1101 edytował ten post 27 maj 2005, 20:29
Powiedz tylko czego, bo cały kod zajmuje 500 KB :)
EDIT:
//BTW przy wątkach powinno odwoływać się do innych procedur (może komponentów też ) poprzez Synchronioze. Odwołujesz się tak?
Nie wiem nawet co to jest :)
Użytkownik -=PcSA=- edytował ten post 27 maj 2005, 20:30
Przy tworzeniu wątku za pomocą repozytorium Delphi daje taki komentarz:
{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure KLASA.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
Użytkownik programista1101 edytował ten post 27 maj 2005, 20:33
Lepiej dam kodzik wątku, bo Synchronize raczej chyba nie da się w tym przypadku użyć :(
Kodzik wątku: http://arturs.aplus....c.php?p=139#139
Jakbyś chciał jeszcze jakiś kawałek kodu to daj znać to dopiszę :)
Użytkownik -=PcSA=- edytował ten post 27 maj 2005, 20:35
Nie używa się czemu ?

Ha :D Udało mi się :). Zrobiłem tak (naturalnie dla przykładu):
Po koleji:
1. Zmienne globalne na Form1:
var forma: TForm; lb: TLabel; //w przykladzie odwolamy sie do TLabel;
2. procedura tworząca komponenty:
{wszytsko dla przykładu} frm := Tform.Create(Application); lb := TLabel.Create(frm); lb.Parent := frm; lb.SetBounds(10, 10, 100, 100); lb.Caption := 'przed odwołaniem'; frm.Show; lb.onclick := go;
3. Umieszczenie procedury "go" w delaracji klasy Form1:
type TForm1 = class(TForm) {...} procedure go(sender: TObject); {...}
4. Uzupełnienie procedury GO:
procedure TForm1.go(Sender: tObject); begin TMojWatek.Create(lb); end;
5. wyglad klasy watku:
uses Classes, StdCtrls; {...} type Tmojwatek = class(TThread) myLab: TLabel; protected procedure Execute; override; public constructor Create(labelek: TLabel); procedure napis; end;
6. Uzupełnienie konstruktora:
constructor Tmojwatek.Create(labelek: TLabel); begin mylab := labelek; inherited Create(False); end;
7. Uzupełnienie procedury Execute:
procedure Tmojwatek.Execute; begin FreeOnTerminate := true; Synchronize(napis); end;
8. uzupełnienie procedury napis:
procedure Tmojwatek.napis; begin myLab.Caption := 'po odwołaniu do dynamicznego labela na dynamicznej formie z watku'; end;
Naturalnie to dla przykładu. Mam nadzieję, że po częsci udało się rozwiązać problem.
Użytkownik programista1101 edytował ten post 27 maj 2005, 21:02
Nie wiem - chyba ma pH. Niestety zrobiłem mniej więcej tak jak Ty to zrobiłeś (mniej więcej, bo chaiłem aby w Gauge coś się zmieniało) i nic nie działa - tzn. zawartość Gauge nie zmienia się - nie ma błędu ale nie zmienia się, a do tego wszystkiego nie mogę korzystać z funkcji zawartych w formie dynamicznie tworzonej :(
A jesli chodzi o ten postep. Masz tak:
for i:=-1 to IloscWpisow-1 do {....} ZamienHaslo.ProgressBar1.Position:= 1 + (i*7); //<- błąd {...} ZamienHaslo.ProgressBar1.Position:= 2 + (i*7); //<- błąd {...} ZamienHaslo.ProgressBar1.Position:= 3 + (i*7);
Przecież to logiczne, że jest błąd skoro "i" na początku jest ujemne.
EDIT:
Zrobilem u siebie też z Gauge i działa.
A jesli chcesz odwoływać się do funkcji i procedur w stworzonej formie to może dodaj parametr forma: TForm w konstruktorze oraz pole w klasie wątku? :unsure:
Użytkownik programista1101 edytował ten post 27 maj 2005, 22:10
A jesli chcesz odwoływać się do funkcji i procedur w stworzonej formie to może dodaj parametr forma: TForm w konstruktorze oraz pole w klasie wątku?
Tform w konstruktorze nie działa (chyba, że coś pomieszałem).
Co do Progress'a to się faktycznie wygłupiłem
A dodałeś do uses moduł Forms oraz pole TForm do klasy wątku? Bo u mnie działa.
BTW. Ale chyba można też wszystkie te funkcje i procedury formy dynamicznej umieścic w sekcji public dowolnej innej klasy...
Użytkownik programista1101 edytował ten post 28 maj 2005, 11:47
Pewnie, że w uses jest moduł Forms :)
BTW. Ale chyba można też wszystkie te funkcje i procedury formy dynamicznej umieścic w sekcji public dowolnej innej klasy...
Właśnie w tym rzecz, że teraz nie wiadomo dla czego kiedy wywołuję jakąś funkcję z formy dynamicznej to w funkcji podczas jej uruchomienia wywala błąd, który nie istnieje kiedy odpalę go już nie z wątku :kwasny:
Oczywiście nie muszę dodawać, że funkcje są w sekcji public
Co do pola TForm - możesz zaprezentować jakiś przykład, bo wydaje mi się, że źle robię to o czym piszesz :lol2:
Hmmm to teraz inaczej - nie używając konstruktra a wszystko dzieki sekcji public Form1. Cel: chcemy na dynamicznie stworzonej formie pokzywać postep na ProgressBar oraz w dowolnym momencie mieć możliwość odwoływania się do procedur/funkcji dla tej formy.
1. W sekcji private klasy TForm1 deklarujemy procedurę odpowiedzialną za stworzenie formy oraz komponentu.
procedure CreateComponents;
2. W sekcji public klasy TForm1 deklraujemy zmienne typu potrzebych komponentów oraz procedury/funkcje do których potem chcemy się odwoływać. Dla przykłądu jedna procedurka:
forma: TForm; Progress1: TProgressBar; procedure OnShowFormy(Sender: TObject); procedure ProceduraFormyDynamicznej;
Procedura OnShowFormy(Sender: TObject); będzie nam służyć do uruchomienia wątku i bedzie wywołana przy pojawieniu sie formy dynamicznej.
3. uzupełniamy procedurę "CreateComponents":
procedure TForm1.CreateComponents; begin forma := TForm.Create(Application); progress1 := TprogressBar.Create(forma); progress1.Parent := forma; progress1.Max := 100; progress1.SetBounds(10, 10, 300, 20); forma.OnShow := OnShowFormy; //to nie jest konieczne - mozna dac cos dowolnego tu poprostru bedzie uruchomienie watku forma.Show; end;
4. uzupełniamy procedurę "OnShowFormy"
procedure TForm1.OnShowFormy(Sender: TObject); begin TWatek.Create(False); end;
5. Uzupełniamy procedurę "ProceduraFormyDynamicznej" - przykładowo.
procedure TForm1.ProceduraFormyDynamicznej; begin if progress1.Position >= 50 then ShowMessage('To już połowa! A dokładnie: ' + IntToStr(progress1.Position); end;
6. Tworzymy nowy moduł, dodajemy go do uses (najlepiej w sekcji implementation) i wstawiamy w niego klasę wątku:
type TWatek = class(TThread) private protected procedure Execute; override; end;
7. uzupełniamy procedurę "Execute":
procedure TWatek.Execute; var i: integer; begin FreeOnTerminate := True; for i := 0 to 100 do begin Form1.Progress1.Position := i; Synchronize(Form1.ProceduraFormyDynamicznej); end; end;
Jak widać w wątku pokazujemy postęp, a także wywołujemy zdeklarowana wcześniej procedurę. W module, gdzie jest klasa wątku nalezy dodac do uses moduł z klasą TForm1.
Gdzieś w kodzie modułu z klasa TForm jeden dajemy:
CreateComponents.
Jesli to nie zadziała to ja już nie jestem w stanie pomóc.
Użytkownik programista1101 edytował ten post 28 maj 2005, 12:30