komponent przekazywanie danych

komponent przekazywanie danych
crowa
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 295
0

Napisalem komponent obslugujacy rozklad pola magnetycznego. Problem pojawia sie przy przekazywaniu procentowego postepu. Załuzmy ze w komponencie jest funkcja:

Kopiuj
procedure jakasfunkcja(var A,B:double;progress:integer);
var i:integer;
begin
 for i:=1 to 100 do
  begin
   B:=A+i;
   progress:=i;
  end;
end;

Taka procedure wywoluje w nowej aplikacji kozystajacej z komponentu:

Kopiuj
 NumericalMethods1.jakasfunkcja(X,Y,ProgressBar1.position);

Niestety nie odzwierciedla sie to na progresbarze

Misiekd
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7923
0

było tyle razy Application.ProcessMessages

crowa
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 295
0

Ale gdzie to wstawic? Bo procedura jakasfunkcja jest w komponencie i do niej sie odwołuje w nowej formie na która stawiam ten komponent.
Probowelem wstawic w kodzie procedury komponentu ale wywala ze nie identyfikuje Application.

Misiekd
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7923
0

Jeśli to jest komponent to to się robi inaczej - tworzysz event, który będzie uruchamiany w momencie zwiększenia progresa o 1. Wtedy podpinasz pod takiego eventa procedurę, która ustawia odpowiednio progressbar. Oczywiście cały kod jakasfunkcja powinien wykonywać się w wątku (o ile to możliwe) aby nie zamrażał aplikacji. Jeśli bardzo nie wiesz jak to zrobić to daj znać na forum to Ci napiszę mniej więcej jak to ma wyglądać

crowa
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 295
0

no wlasnie nie za bardzo wiem. Wiec sprawa wygląda tak:
jest sobie procedura obliczania metoda choleskyego,gaussa,crouta,gradientów itp. Musze mieć procentowe wskazania postepu dla kazdej z nich.
Caly kod komponentu wstawilem na ftp.
ftp.lanet.net.pl
user:u101099
pasword:highlander82
Spojrz jesli mozesz na to.
Dzienx [browar]

Misiekd
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7923
0

najpierw kilka uwag

  1. jak nie zmieniasz wartości zmiennych to nie przekazuj ich przez wartość, np
Kopiuj
procedure TNumericalMethods.multiplication_vectors(var A,B:Tvector;var Result:double);
var i:integer;
begin
 FMethod:='multiplication_vectors';
 if length(A)<>length(B) then raise Exception.Create('procedure multiplication_vectors return fatal error code:'+#13+'Actual size of A,B:Tvector mismatch');
 Result:=0;
 for i:=low(A) to high(A) do Result:=Result+A[i]*B[i];
end;

poprawnie powinno być

Kopiuj
function TNumericalMethods.multiplication_vectors(A,B:Tvector): double;
var 
  i:integer;
begin
  FMethod := 'multiplication_vectors';
  if length(A) <> length(B) then 
    raise Exception.Create('procedure multiplication_vectors return fatal error code:'+#13+'Actual size of A,B:Tvector mismatch');
  Result:=0;
  for i := low(A) to high(A) do 
    Result := Result + A[i] * B[i];
end;
  1. na początku zadeklaruj sobie typ wyliczeniowy
Kopiuj
type
  TMetodType = (mtMultiplicationVectors, mtValidateMultiplicationVectorMatrix, mtMultiplicationNumberVector, ...)

i potem zmień tym pola Method ze string na TMetodType - user będzie mógł wybrać metodę z listy a nie wpisać cokolwiek. write zmienił bym na SetMethod i w procedurze obsługi oprócz ustawiania FMetod ustawiał bym też FAboutMetod

  1. ja bym to trochę inaczej zrobił bo tak jak masz teraz to na dobrą sprawę całe opakowanie w komponent jest dla picu tylko. Wszystkie potrzebne do obliczenia zmienne (także wyjściowe) przerobił bym na pola, dodał jedną metodę Execute oraz zmienił jak w 2 napisałem. W Execute na podstawie FMetod sprawdzał bym czy odpowiednie pola są wypełnione i czy wypełnione są poprawnie i jeśli tak to odpalał bym odpowiednią metodę (wszystkie te wywołania zrobiłbym prywatne).
    Oczywiście trzeba by dla TVector, TMatrix itd napisać jeszcze edytory ale przynajmniej by to wtedy porządnie i fachowo wyglądało :)

dobra, pomarudziłem to teraz event :)

Kopiuj
type
  TProgressEvent = procedure(Max, Pos: Integer) of object;

type
  TNumericalMethods=class(TComponent)
  private
    { Private declarations }
    FOnProgres: TProgressEvent;
  protected
    { Protected declarations }
  public
    { Public declarations }
  published
    { Published declarations }
    property OnProgres: TProgressEvent read FOnProgres write FOnProgres;
  end;

i w funkcji, która ma uaktualniać progresa

Kopiuj
procedure ....
begin
  ...
  if Assigned(FOnProgres) then
    FOnProgress(Max, Pos);
  ...
end;

i jeszcze trzeba dopisać samą obsługę progressbara ale to już banalne

z tym, że jeśli te obliczenia nie będą w osobnym wątku to program i tak będzie "zamarzał" na czas ich wykonywania

crowa
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 295
0
Misiekd napisał(a)

najpierw kilka uwag

  1. jak nie zmieniasz wartości zmiennych to nie przekazuj ich przez wartość, np
Kopiuj
procedure TNumericalMethods.multiplication_vectors(var A,B:Tvector;var Result:double);
var i:integer;
begin
 FMethod:='multiplication_vectors';
 if length(A)<>length(B) then raise Exception.Create('procedure multiplication_vectors return fatal error code:'+#13+'Actual size of A,B:Tvector mismatch');
 Result:=0;
 for i:=low(A) to high(A) do Result:=Result+A[i]*B[i];
end;

poprawnie powinno być

Kopiuj
function TNumericalMethods.multiplication_vectors(A,B:Tvector): double;
var 
  i:integer;
begin
  FMethod := 'multiplication_vectors';
  if length(A) <> length(B) then 
    raise Exception.Create('procedure multiplication_vectors return fatal error code:'+#13+'Actual size of A,B:Tvector mismatch');
  Result:=0;
  for i := low(A) to high(A) do 
    Result := Result + A[i] * B[i];
end;

Mam pytanie czy nie powoduje to kopiowanie do procedury tej tablicy tzn jak ja wywolam od tabA a w procedurze jest A to chyba nastepuje kopiowanie z tabA do A. Przekazuje dane przez referencje. Pola FMethod i AboutMethod to tylko informacje dla usera. w trybie silent nie sa przekazywane i np user nie widzi ze wykonuja sie odpowiednie czesci procedury.
Jeśli chodzi o tego eventa to mam napisac eventa, a w nim wszystkie procedury powinny byc? bo to nie wykonalne od strony uzytkowania. Uzytkownik podaje NumericalMethods1.v_multiplication_matrix_vector(dane.....) i to mu leci. Musialby tak jak mówisz zmienic Method na typ wyliczeniowy i case of Fmethod wywolywac w evencie dana procedure.

Kopiuj
type Fmethod=(metoda1,metoda2,metoda3....)

a potem wywolanie w event

Kopiuj
case metoda(jest typu Fmethod) of
 metoda1: begin
               end
itd.

Dobrze myśle?? Tablice które obsługuje maja rozmiar 10000x10000

Misiekd
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7923
0

ech tu masz przykładowy projekt + komponent który pokazuje ideę :)
Twój kod liczący coś trzeba umieścić w ExecuteNormal zamiast tej pętli przy pracy bez wątków lub w Execute (wątku) jeśli ma liczyć w wątku

Np. metoda Crout_method mogła by wyglądać tak (nie wiem czy FMax nest dobrze policzone ale powinno być mniej więcej tyle przebiegów w wybranych pętlach)

Kopiuj
var
  APos: Integer;
  i, j: integer;
  L, U: Tmatrix;
  Y: Tvector;
begin
  APos := 0;
  FMax := Length(B) * 4 + Length(Result);

  if SilentMode=false then
  begin
    FMethod:='Crout_method';
  end;
  Setlength(L,length(B));
  Setlength(U,length(B));
 
  //*********
  for i:=low(L) to high(L) do
  begin
    Setlength(L[i],i+1);
    Setlength(U[i],length(U)-i);
    DoProgress(APos);
    Inc(APos);
  end;
  //*********

  Setlength(Y,length(B));
  Crout_factorization(A,val_A,L,U);

  //********
  for i:=low(Y) to high(Y) do 
  begin
    Y[i]:=B[i];
    DoProgress(APos);
    Inc(APos);
  end;
  //***********

  for i:=low(Y) to high(Y) do
  begin
    Y[i]:=Y[i]/L[i,i];
    for j:=i+1 to high(Y) do 
      Y[j]:=Y[j]-L[j,i]*Y[i];
    DoProgress(APos);
    Inc(APos);
  end;


  for i:=high(Y)-1 downto low(Y) do
  begin
    for j:=low(Result) to i do 
      Y[j]:=Y[j]-U[j,high(U)-(i+1)]*Y[i+1];
    DoProgress(APos);
    Inc(APos);
  end;

  for i:=low(Result) to high(Result) do 
  begin
    Result[i]:=Y[i];
    DoProgress(APos);
    Inc(APos);
  end;

  Finalize(L);
  Finalize(U);
  Finalize(Y);
  
  if Assigned(FOnDone) then
    FOnDone(Self);
end;

aa DoProgress wygląda tak

Kopiuj
procedure TTestComp.DoProgress(Pos: Integer);
begin
  if Assigned(FOnProgres) then
    FOnProgres(Self, FMax, Pos);
end;
crowa
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 295
0

nie moge tego zassać. Jak mozesz wrzuc na ftp.lanet.net.pl
user:u101099, pasword:highlander82
Dzienx
[browar] for You

Misiekd
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7923
0

poszło

BTW czemu nie możesz pobrać z 4p? co Ci wyskakuje?

crowa
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 295
0

Pakiet o tym ID nie istnieje
[diabel]

Misiekd
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7923
0

mi się otwiera normalnie :) no ale masz na ftpie

crowa
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 295
0

Dzienx MisiekD o to chodziło [browar]
Heh jeszcze sie musze dużo nauczyc co do programowania komponentów :/

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.