Magno 4 Posted January 11, 2021 Well, I have a panel with 3 labels. My app will geocode reverse (TMaps) some information and I simply need to make it happen (show the address info) after the decoding. Example: procedure Tform.OnGeocodeReverseEvent(const Address: TCivicAddress); begin // these labels are into a Panel labe1.Text := Address.Thoroughfare; labe2.Text := Address.Locality; labe3.Text := Address.CountryName; end; I've tried to force refresh: Panel1.InvalidateRect(RectF(0, 0, Panel1.Width, Panel1.Height)); Also tried create a new "refreshable" panel based on a Stackoverflow example I saw, using SubscribeToMessage(). As expected the geo reverse occurs into a thread (TTask) and after I read the info I need to call the GeocodeReverse() That geoData var bellow simply record that carries some information I will need later, but basically what I need to send to my geoDecode function is just the position (lat/lon), as simplified code: procedure TForm.UpdateInfo(); begin TTask.Run( procedure begin try GetGeoData(); finally TThread.Synchronize(nil, procedure begin UpdateMap(geoData); geoDecode(geoData.Position); end); end; end); end; procedure TForm.geoDecode(Position: TMapCoordinate); var NewLocation: TLocationCoord2D; begin try // Setup an instance of TGeocoder if not Assigned(FGeocoder) then begin // ShowMessage('FGeocoder'); if Assigned(TGeocoder.Current) then FGeocoder := TGeocoder.Current.Create; if Assigned(FGeocoder) then FGeocoder.OnGeocodeReverse := OnGeocodeReverseEvent; end; // Translate location to address if Assigned(FGeocoder) and not FGeocoder.Geocoding then begin // ShowMessage('NewLocation'); NewLocation.Latitude := Position.Latitude; NewLocation.Longitude := Position.Longitude; FGeocoder.GeocodeReverse(NewLocation); end except ShowMessage('Erro ao acessar serviço de geocoder'); end; end; So, after all the OnGeocodeReverse is triggered nicely but the labels themselves will only update if I, e.g. change to another tab, open close the multiviewer, something that force the redraw of the panel. Share this post Link to post
Guest Posted January 11, 2021 when working with UI components and THREAD is necessary take care about multi-write, because the compnents is not secure receive write-concurrent, like Multi-users in Database, you see? (english is not my laguage, sorry) you need always "LOCK / UNLOCK" for threads works correct if this is the case of your problem here. Share this post Link to post
Rollo62 536 Posted January 12, 2021 procedure Tform.OnGeocodeReverseEvent(const Address: TCivicAddress); begin end; You should consider that this event is triggered by separate hardware, and it may or may not occur in the mai UI thread. I would decouple the results, and use TThread.ForceQueue to ensure that main UI is vaild. Share this post Link to post
Magno 4 Posted January 12, 2021 2 hours ago, Rollo62 said: procedure Tform.OnGeocodeReverseEvent(const Address: TCivicAddress); begin end; You should consider that this event is triggered by separate hardware, and it may or may not occur in the mai UI thread. I would decouple the results, and use TThread.ForceQueue to ensure that main UI is vaild. Gonna give a try on that! Thanks so far Share this post Link to post
Magno 4 Posted January 12, 2021 Well, so far not success. I've even tried to trigger a TTimer just see if would work, but no 😕 Share this post Link to post
Pat Foley 51 Posted January 12, 2021 (edited) Quote So, after all the OnGeocodeReverse is triggered nicely but the labels themselves will only update if I, e.g. change to another tab, open close the multiviewer, something that force the redraw of the panel. If that's all you need just try show or set focus event to get the windows attention. I think it would work better without the thread your callback event would simply wait its turn behind mouse events. Edited January 12, 2021 by Pat Foley Share this post Link to post
Guest Posted January 13, 2021 On 1/11/2021 at 12:46 PM, Magno said: something that force the redraw of the panel. review your THREAD use, maybe is there where the problem is in! look my sample about TTask RUN procedure TForm1.Button1Click(Sender: TObject); begin // Label1 is in Panel1 if not(Label1.Parent = nil) then begin Caption := Label1.Parent.ToString; // TPanel // Label1.Parent.Repaint; // call Invalidate and Update to repaint the control // // procedure TWinControl.Invalidate; // Vcl.Controls.pas // Perform(CM_INVALIDATE, 0, 0); // Vcl.Controls.pas // function TControl.Perform(Msg: Cardinal; WParam: WPARAM; LParam: LPARAM): LRESULT; // Vcl.Controls.pas // ------ // procedure TWinControl.Update; // Vcl.Controls.pas // function UpdateWindow; external user32 name 'UpdateWindow'; // WinApi.Windows.pas end; end; hug Share this post Link to post
Magno 4 Posted January 20, 2021 On 1/12/2021 at 11:14 PM, emailx45 said: review your THREAD use, maybe is there where the problem is in! look my sample about TTask RUN procedure TForm1.Button1Click(Sender: TObject); begin // Label1 is in Panel1 if not(Label1.Parent = nil) then begin Caption := Label1.Parent.ToString; // TPanel // Label1.Parent.Repaint; // call Invalidate and Update to repaint the control // // procedure TWinControl.Invalidate; // Vcl.Controls.pas // Perform(CM_INVALIDATE, 0, 0); // Vcl.Controls.pas // function TControl.Perform(Msg: Cardinal; WParam: WPARAM; LParam: LPARAM): LRESULT; // Vcl.Controls.pas // ------ // procedure TWinControl.Update; // Vcl.Controls.pas // function UpdateWindow; external user32 name 'UpdateWindow'; // WinApi.Windows.pas end; end; I just saw the thread, that's a nice code, you're using TProc, I never thought about that, well I will study it and so far thank you. Share this post Link to post