komponent przekazywanie danych

0

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

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:

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

Niestety nie odzwierciedla sie to na progresbarze

0

było tyle razy Application.ProcessMessages

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.

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ć

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]

0

najpierw kilka uwag

  1. jak nie zmieniasz wartości zmiennych to nie przekazuj ich przez wartość, np
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ć

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
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 :)

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

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

0
Misiekd napisał(a)

najpierw kilka uwag

  1. jak nie zmieniasz wartości zmiennych to nie przekazuj ich przez wartość, np
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ć

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.

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

a potem wywolanie w event

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

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

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)

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

procedure TTestComp.DoProgress(Pos: Integer);
begin
  if Assigned(FOnProgres) then
    FOnProgres(Self, FMax, Pos);
end;
0

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

0

poszło

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

0

Pakiet o tym ID nie istnieje
[diabel]

0

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

0

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

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