Toon posts:

[Delphi 7] informatie doorspelen naar mainform

Pagina: 1
Acties:

Verwijderd

Topicstarter
Een goedezondagmorgen mensen!

Ik heb een simpele vraag waar volgens mij ook een simpel antwoord op te vinden moet zijn. Jammer genoeg kan ik dit antwoord tot nu toe nog nergens vinden :| . Wie helpt mij uit de brand?

Situatie: In Delphi heb ik één standaard form met bijbehorende unit. Daarnaast heb ik nog enkele classes aangemaakt, elk in een eigen unit.

Wat ik wil: Nu gebeurt er nogal wat in de constructor van enkele classes, zodoende dat ik graag wat (debug) info door zou willen spelen aan het form (bv "Initialisatie van array ... gelukt" etc etc), om deze mooi in een memo'tje or whatever te gooien.

Maar: De meest simpele manier is uiteraard om in de "uses" van een class (of liever gezegd: de unit die bij die class hoort) de unit van het form te zetten. Maar dat is uiteraard HEEL ERG LELIJK. Is er geen elegantere manier om die te doen?

  • Sybr_E-N
  • Registratie: December 2001
  • Laatst online: 20:00
Het is lang geleden dat ik voor het laatst met Delphi in aanraking kwam, maar kun je niet je mainform meegeven aan de constructor's van die andere klassen? Dat je dan in die andere klassen gewoon een pointer hebt naar je mainform.

  • Paul
  • Registratie: September 2000
  • Laatst online: 02-05 07:01
Wat is daar HEEL ERG LELIJK aan? Dat is hoe Delphi werkt... Of bedoel je dat je de GUI en de logica gescheiden wilt houden?

Wat je kunt doen is in je klasses een event proggen dat als param de statusmessage meekrijgt die je vervolgens in je GUI gebruikt, of, als je logica uit threads bestaat, een producer/consumer-achtig iets met een queue. Dan produceert je logica een aantal messages die je consumer op het scherm tovert.

Edit: Cybr_E-N: ook dan moet je de mainform in de uses zetten, omdat Delphi anders niet weet wat er "in" die pointer zit.
Met een beetje pech heb je zelfs de logica-klasses in de uses van je declaration staan in de mainform omdat je er instanties van wilt hebben binnen je mainform-klasse, en dan krijg je een circular reference, dan hebben ze elkaar in de uses (in de declaration, in de implementation-sectie maakt het niet uit).

[ Voor 34% gewijzigd door Paul op 22-05-2005 11:42 ]

"Your life is yours alone. Rise up and live it." - Richard Rahl
Rhàshan - Aditu Sunlock


Verwijderd

Topicstarter
Allebei bedankt!

Inderdaad, ik wil de GUI en de logica gescheiden houden. Maar ik denk dat het toch wel met Sybr_E-N's oplossing kan. In de class maak ik een pointer aan naar een form (of memo of whatever) dus ik hoef in de uses niets extra's te vermelden. Ik heb t zojuist geprobeerd en t werkt. Klein probleempje nog: je kunt de volgens mij de pointer pas toewijzen NA de constructor - (class.Create) - dus alles wat IN de constructor gebeurt kan ik nog niet gebruiken...

  • Paul
  • Registratie: September 2000
  • Laatst online: 02-05 07:01
Tja, je kunt een TMemo meegeven aan de constructor waar je vervolgens al je messages op klad, maar in feite ben je met deze oplossing nog steeds met de GUI bezig in je logica :)

"Your life is yours alone. Rise up and live it." - Richard Rahl
Rhàshan - Aditu Sunlock


Verwijderd

Topicstarter
Ja idd....

Events zou misschien een oplossing zijn, maar is het niet zo dat ik dan uiteindelijk ook weer op een ref naar de GUI uitkom?

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Je zal dan een logging structuur moeten maken. Een singleton class waar iedereen meldingen aan kan toevoegen. Als je daarbij een observer structuur maakt kan het mainform zich daarop abboneren en reageren wanneer er een melding wordt toegevoegd. Maar je zou ook een andere observer kunnen maken die het direct naar een bestand weg schrijft en doorstuurd via tcp/ip.

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
@ LordLarry:

Die mogelijkheden heb ik ook al bekeken, maar in het 1e geval zullen de classes de logclass ook moeten 'usen', en de logclass zal de formclass aan moeten spreken -> circular reference. En in het 2e geval zal de observer om de zoveel tijd moeten kijken naar logentries, en dat heeft als grote nadeel dat het niet realtime is, en dat is erg lastig mbt bv debuggen...

Maar toch bedankt voor je reactie ;)

  • charlie
  • Registratie: Oktober 2000
  • Laatst online: 07-03 11:08

charlie

?*?

Kan je niet gewoon een methode bijmaken in je klasse waarmee je de debugging informatie ophaalt (die je natuurlijk dan wel eerst in een locale variabele opslaat).

Dan kan je vervolgens op je main form een button aanmaken die de info ophaalt en in een Textbox oid zet (of dmv een timer of zo)

Verwijderd

Topicstarter
Voor het progje waar ik mee bezig ben moet ik waarschijnlijk uiteindelijk het uiterste vragen van mijn cpu, dus ik wil het echt realtime, zonder omwegen, zonder timers etc doen. Dus heel simpel, mijn class zegt: "Flikker deze [..] meuk in het log!" en BAM! het staat er. :Y)

  • Paul
  • Registratie: September 2000
  • Laatst online: 02-05 07:01
Nee, events zijn een soort van producer/consumer maar dan single-threaded. Je zegt "ik heb een message voor de GUI, eens kijken of die heeft aangegeven hem te willen hebben. Ja, hebbesn hiier GUI, een message, zie maar wat je er mee doet" :) In je logica houd je jezelf dus niet bezig met hoe het op het scherm komt, alleen maar dat er "iets" mee gedaan wordt door de GUI :)

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type 

TMyMessageEvent = procedure(Sender: TObject; MyMessage: string);

TBlaat: Class
  private
    FOnMyMessageToTheWorld: TMyMessageEvent;
  public
    property OnMyMessageToTheWorld: TMyMessageEvent read FOnMyMessageToTheWorld write FOnMyMessageToTeWorld;
  end;

procedure TBlaat.DoeIets;
begin
  DoeDit();
  DoeDat();
  if Assigned (FOnMyMessageToTheWorld) then
    FOnMyMessageToTheWorld(self, "DoeIets uitgevoerd");
end;


Ik begin echter in je antwoorden (met name nu ook tegen LordLarry) een of andere onrationele afkeer van de Uses-clause te bespeuren? Ik heb echt zelden tot nooit hoofdbrekens over circular references?
Die logger hoeft in princiepe niets te weten van de mainklasse, die kan gewoon een TMemo oid vn de mainform krijgen om op te kladden. Of je gebruikt ook daar events.

Overigens, als een observer ergens op abonneert (juist als men zich abonneert) dan zorgt de controller ervoor dat de abonnee de gegevens krijgt.
Observer/controller, producer/consumer, events, ze komen op hetzelfde neer (nou ja, bij producer/consumer staat de consumer "actief" te wachten tot er iets geproduceert is), en bij geen van drieen krijg je circular references...

Edit: Als je echt zoveel van je CPU gaat vragen dan zou ik de logica in een aparte thread stoppen, anders is je GUI 'dood' (Delphi krijgt niet de tijd om zijn message-queue af te werken) tenzij je echt overal Application.ProccessMessages aan gaat roepen. Ook worden dan (dus) meldingen van je log niet meer op het scherm gezet, zonder dat Delphi zijn queue kan doorlopen wordt dus ook de Repaint niet uitgevoerd.

[ Voor 13% gewijzigd door Paul op 22-05-2005 12:24 ]

"Your life is yours alone. Rise up and live it." - Richard Rahl
Rhàshan - Aditu Sunlock


Verwijderd

Topicstarter
Ach zo! Sorry, ik had je verkeerd begrepen. En bedankt voor het voorbeeldje!

En nee, ik heb niet echt een irrationele afkeer tegen uses hoor :) , en al helemaal niet tegen LordLarry ;) sorry als ik zo overkwam.

Goed, hier ga ik mee aan de slag, bedankt iedereen voor jullie snelle reacties! _/-\o_

Edit: Het freezen van mijn scherm kan ik toch zeker wel oplossen met ProcessMessages? O wacht ja maar die moet ik dus ook om de zoveel tijd aanroepen....mmm.... dan toch maar eens naar multithread gaan kijken :'(

[ Voor 27% gewijzigd door Verwijderd op 22-05-2005 12:33 ]


  • Paul
  • Registratie: September 2000
  • Laatst online: 02-05 07:01
Verwijderd schreef op zondag 22 mei 2005 @ 12:30:
Ach zo! Sorry, ik had je verkeerd begrepen. En bedankt voor het voorbeeldje!

En nee, ik heb niet echt een irrationele afkeer tegen uses hoor :) , en al helemaal niet tegen LordLarry ;) sorry als ik zo overkwam.

Goed, hier ga ik mee aan de slag, bedankt iedereen voor jullie snelle reacties! _/-\o_

Edit: Het freezen van mijn scherm kan ik toch zeker wel oplossen met ProcessMessages? O wacht ja maar die moet ik dus ook om de zoveel tijd aanroepen....mmm.... dan toch maar eens naar multithread gaan kijken :'(
Ik zeg ook niet dat je een afkeer hebt van LordLarry :+ maar dat je daar weer over die uses begon :P Je weet dat de implementation-sectie ook een uses kan hebben? ;)

Het freezen van je scherm kun je inderdaad oplossen dmv Application,ProcessMessages, maar als je VEEL rekenwerk hebt is het altijd beter dit in een aparte klasse te doen, als was het maar zodat je mainthread zijn taak kan blijven doen. Threads zijn overigens helemaal niet zo moeilijk :) Alleen denk ik dat events in een thread niet zo'n goed idee is, tenzij je de event aanroept in een Synchronize'd procedure :)

Wat je dan wel kunt doen is zelf messages in de queue gaan gooien, die je in de mainform apart afvangt (of het moet een WM_SetText zijn van een component dat die ondersteunt (o.a. TStatusBar op de Win32-tab). Zoek maar op de API-call ( en Delphi voorbeeldjes, als je het noet zo kent is het vrij lastig, ik heb er ook redelijk lang mee lopen worstelen voordat ik het doorhad, ik heb daar alleen geen code van bij de hand) SendMessage en SendMessageEx :)

"Your life is yours alone. Rise up and live it." - Richard Rahl
Rhàshan - Aditu Sunlock


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Verwijderd schreef op zondag 22 mei 2005 @ 12:09:
Die mogelijkheden heb ik ook al bekeken, maar in het 1e geval zullen de classes de logclass ook moeten 'usen', en de logclass zal de formclass aan moeten spreken -> circular reference. En in het 2e geval zal de observer om de zoveel tijd moeten kijken naar logentries, en dat heeft als grote nadeel dat het niet realtime is, en dat is erg lastig mbt bv debuggen...
Ja, iedereen die wil loggen zal de log unit moeten usen, maar de log unit heeft helemaal geen relatie met wel GUI onderdeel dan ook. Daar zorgt het Observer Pattern voor. Men kan zich abbonneren de log class en die zal men een seintje geven wanneer er wat aan het log wordt toegevoegd. Een hele simpele observer constructie is wat in [rml]Paul Nieuwkamp in "[ Delphi 7] informatie doorspelen naar ma..."[/rml] wordt getoond.

Overigens zijn circular references vaak heel goed te voorkomen door de meeste units te usen in de implementation sectie en niet alleen in de implementation sectie.

PS: Als je je log class gaat gebruiken icm threads moet je wel zorgen dat de class thread safe is, maar dat is voer voor een heel nieuw topic.

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Enige tijd geleden had ik een vergelijkbare vraag. Zie:
Hoe GUI en berekening scheiden? http://gathering.tweakers.net/forum/list_messages/1030587.

Misschien heb je er wat aan.
Pagina: 1