» »

[c++] standardni c++ in dogodki(events)

[c++] standardni c++ in dogodki(events)

zhigatsey ::

Živjo,

Bom na primeru razložil...
Imam razred, ki kopira datoteko....
In rad bi da bi lahko prikazoval napredek koliko datoteke je že prekopirane...
Torej rabim nekakšen dogodek "OnProgress" ali kaj podobnega...
Samo kako to narediti v standardnem c++-u... na najbolj eleganten način...

Mogoče bi naredil kaj podobnega kot v wxWidgets... seveda še nimam pojma kako, tole so najbrž nekakšni makroji...

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU (wxID_EXIT, MyFrame::OnExit)
EVT_MENU (DO_TEST, MyFrame::DoTest)
EVT_SIZE ( MyFrame::OnSize)
EVT_BUTTON (BUTTON1, MyFrame::OnButton1)
END_EVENT_TABLE()

Če imate kakšen predlog bi bil zelo vesel...

Hvala za odgovore

Senitel ::

Multithreading... Narediš thread ki kopira in povečuje en števec (progress), in potem iz glavnega threada ta števec bereš.

Jean-Paul ::

Poleg multithreadinga lahko uporabiš še rešitev s callbacki. Če si v C++ svetu, svetujem libsigc++.

zhigatsey ::

Najprej hvala za predlog si bom ogledal , čeprav bi rad to naredil brez zunanjih knjižnjic...
V mislih sem imel kakšno rešitev s kazalci na funkcije... Moram še malo pogledati vso zadevo...
V glavnem čimbolj simple, elegantno in pregledno...

Zgodovina sprememb…

SasoS ::

Odvisno kakšna je sploh aplikacija...Windows, wxWidgets, SDL, Qt, karkoli? Tam imaš najbrž nek event loop in sprogramiraš da iz razreda prebere trenutno pozicijo ali pa da razred tja pošilja evente...

zhigatsey ::

Aplikacija je napisana v standardnem c++-u....
Za primer sem dal razred za kopiranje datoteke,
v katerem se proži event v katerem bi recimo prikazoval napredek kopiranja datoteke...

V mislih sem imel podobno zgradbo kot pri delphiju...

// Pišem na pamet, samo za primer

// ko narediš tip dogodka, ki je v bistvu kazalec na funkcijo
type TProgressEvent = procedure (Sender: TObject; Progress: Integer) of object;

in potem v razredu narediš takole

// deklaracija razreda
TCopyFile = class
private
  FOnProgress: TProgressEvent; // deklariramo privatno spremenljivko tipa TProgressEvent
public
  procedure Copy(Source: string; Dest: string);
  property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
end;
//-------------------
procedure TCopyFile.Copy(Source: string; Dest: string);
var
  Progress: Integer;
begin
  // V tej metodi se datoteka kopira po delih (iz enega src bufferja v dest buffer, in nekako izračunaš procent in sprožiš event)
  Progress := 45; // samo za primer kakor da je prekošpirane že 45% datoteke

  // Tukaj prožimo event
  if Assigned(FOnProgres) then
    FOnProgress(Self, Progress);
end;


// Zdaj pa še kako bi vse skupaj uporabil

// Najprej napišemo proceduro (Nekje v glavnem programu), katero bo razred klical -> to je malo bolj okorno razloženo:)
procedure CopyFileProgress(Sender: TObject; Progress: Integer);
begin
  //Prikaži progress v text boxu naprimer
  Edit1.Text := IntToStr(Progress);
end;

//-------------------------------------

with TCopyFile.Create do
try
  OnProgress := CopyFileProgress; // Tukaj določimo naj kazalec kaže na funkcijo CopyFileProgress
  Copy(src, dest);
finally
  Free;
end;


Seveda mislim da se da to na podoben način narediti tudi v standardnem c++-u... Zdajle ne vidim razloga zakaj ne...
To bi bila meni najlažja varianta... Sem pa gledal tudi kako narediš kao statične evente brez pointerjev na funkcije
to je pa na telje strani razloženo tukajle,
samo se moram še odločiti kako pa kaj... Ne vem pa še dobro kako delujejo -> jaz jih bom poimenoval "event maps",
tako je narejeno v mfc ali pa v wxWidgets.... in če kaj podobnega pride v poštev....

In pa to delam ljubiteljsko za razširitev svojega znanja...

Hvala za odgovore

SasoS ::

Jah to lahko narediš na enak način:

// Deklariraš tip pointerja na proceduro
typedef void (*CopyFileProgress)(int);

// Ena izmed možnh procedur
void CopyFile(int progress)
{
    nekmeni.SetText(progress);
}

class Copy
{
private:
    CopyFileProgress myproc;
    // Copy metoda
    CopyData()
    {
        ...
        if(myproc)
            myproc(progress);
        ...
     }
public:
    // Initializiraj myproc na NULL v konstruktorju
    Copy():myproc(NULL) { }
    // Metoda za določanje procedure
   SetProc(CopyFileProgress proc):myproc(proc) { }
};

int main()
{
    Copy *copy = new Copy;
    copy->SetProc(CopyFile);
    copy->CopyData();
}


Nekaj v tem stilu, zelo nahitro spisano.

zhigatsey ::

Ja tako bi bilo super samo pomoje da ne bo šlo tako zlahka kot sem mislil, sicer nisem ravno siguren, bom sprobal
Ker moraš deklarirati function pointer za memberja classa....

nekaj takega brez typedefa
void (Copy::*progress)(int);

Samo se pa spet zakomplicira pri dedovanju, ne bom imel za isti event v vsakem podedovanem razredu
drug typedef....

Se bo treba pomoje nekaj drugega izmisliti.....

Gundolf ::

class CopyObserver {
   virtual copyProgress(float progress) = 0;
};

class WhereCopyIsUsed {
   CopyObserver* myObserver;

   void copy() {
      ...
      if (myObserver != 0) myObserver->copyProgress(progressState);
   }
};

Izpelješ svoj class iz CopyObserverja in to je to.

Gundolf ::

Še en način primeren, če se količkokaj spoznaš na template.
class WhereCopyIsUsed {
public:
   template<class CopyObserver>
   void copy(CopyObserver& observer) {
      ...
      while (copyOneStep) 
         observer.onCopyProgress(copyProgress);
      ...
   }
};

// ko kličeš copy
class SomeDialog {
public:
   void onCopyProgress(float progress) {
      ...
      // tu pišeš progress v tvoj textbox ali delaš kaj podobnega
   }

   void copySth() {
      ...
      WhereCopyIsUsed myCopyObj;
      myCopyObj.copy(*this);
      ...
   }
}

Zgodovina sprememb…

  • spremenil: Gundolf ()

zhigatsey ::

Aha hvala samo se mi na prvi pogled zdi da je to bolj rešitev zgolj za ta primer kopiranja datotek...
Našel sem pa tale zanimiv članek, ki si ga bom bolj podrobno prebral doma, najbrž da bo tukaj našel veliko odgovorov na moja vprašanja....

Gundolf ::

Ja delegati so dobra rešitev. V bistvu podobno mojemu drugemu predlogu, le da je tisti template skrit in da je bolj razširljivo. Če te zanese v to smer imaš za to že pripravljeno knjižnico Loki. Dokaj enostavna zadeva (nobenega bloata ni), vključuje pa nekaj močnih patternov. Avtor (oz. eden izmed njih) je velika avtoriteta v C++, Andrei Alexandrescu.

V Lokiju se zadeva imenuje Functor. Lahko takoj sprobaš, če je to tista idealna rešitev zate (seveda je bolje, če si prebereš tvoj članek in se še kaj naučiš zraven ;)). Če takole na pamet kodo napišem:
#include <Loki/Functor.h>

class Krneki {
   int mojaFunkcija(int a, int b) {return a + b}
}

Krneki mojObjekt;
Loki::Functor<int> func(mojObjekt, mojaFunkcija);
tri = func(1, 2);

Zgodovina sprememb…

  • spremenil: Gundolf ()

yeti ::

Zal manjka en podatek; kateri sistem?

Na windowsih je, za povecevat progres bar, klasicna varianta da nekaj opravljas v locenem threadu, potem pa od tam posiljas podatke kar direktno oknu preko messegov (ki so thread safe). ni pa sploh nujno, da delaš zadevo preko threada, samo se ti nič (razen progress bara) ne bo osveževalo (no ja, tudi to se da postimat samo je bolj preprosto naredit thread).

pseudo, poglej si kaj je pravi message v msdn;

createthread(..., threadfcn, hwnd);

int threadfcn(handle hwnd)
{
for(i = 0; i++)
{
sendmessage(hwnd, WM_PROGRESS, i, 0);
}
}

Zgodovina sprememb…

  • spremenil: yeti ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[Android] setText iz AsyncTask

Oddelek: Programiranje
7798 (715) golobich
»

[C#] pixel scan z Thread

Oddelek: Programiranje
121086 (868) perooo25
»

C# BackgroundWorker Class problem

Oddelek: Programiranje
61195 (1151) hendriks
»

[JAVA]Barvni string v labeli

Oddelek: Programiranje
8868 (796) Infinity
»

[razvoj] klon windows commanderja za linux (strani: 1 2 3 )

Oddelek: Programiranje
1006398 (4437) napsy

Več podobnih tem