Recent

Author Topic: TButton & TRadioButton don't trigger TEdit OnExit or OnEditingDone. Workaround!  (Read 4751 times)

lor

  • New Member
  • *
  • Posts: 26
Here's a workaround I devised to overcome the problem described further below:

In coming up with this I discovered that an OnClick event occurs before the OnEnter event for same control, (perhaps this is explained somewhere in the documentation but I hadn't seen it) and the OnEndEditing event for the prior control is not triggered until the OnEnter occurs for the new control.

What I did was add an OnClick action to every button and radio button; and put an extra button on the form, shown below as ButtonSemaphore; and made a form class method, to be shared by all the OnClicks, that assigns the form.ActiveControl to be ButtonSemaphore, which occurs before the OnEnter following the OnClick. The assignment to ButtonSemaphore causes the OnEndEditing to occur for the previously vacated TEdit, then the new control is resumed at its OnEnter entry point.

Here are examples of the click and shared procedures:

procedure TForm1.RadioTxINIClick(Sender: TObject);
begin
    ForceEditingDoneOnTEdits(Sender);
    ... other process, if any...
end;

procedure TForm1.ForceEditingDoneOnTEdits (Sender :TObject);
begin
    ButtonSemaphore.Show;
    ActiveControl := ButtonSemaphore;
    ButtonSemaphore.Hide;
end;

The Show and Hide render the semaphore button invisible to the user. It should be defined as not visible to start with. The Show allows the assignment to occur, because focus assignments are forbidden to invisible and/or disabled controls.


Original Problem:

When a TButton or TRadioButton control is clicked, the previously changed TEdit control .OnExit or .EditingDone actions do not occur. They do occur if another TEdit control is entered, however. How can I change this behavior so that the TEdit controls get exit and/or done actions activated when a button os pushed? I'd rather not have to monitor edit fields and change the entry of every button to call the edit control exit actions. Thanks for enlightening me!

Now here I've added the requested test case program.

Lazarus 1.2.6  FPC 2.6.4  Mac OSX 8.5  i386-darwin-carbon

So below is a little test program for TEdit. It shows two TEdit controls, a TButton control with no action, a TButton that terminates the program, and a TRadioButton that has no action. 

Changes to Edit1 are reflected in Edit2 when Edit1 actions are EditingDone and/or Exit.

When Edit1 gets focus with a mouse click, it's Text is saved and then set to be empty in anticipation of the entry of new data by the user. When the Exit or EditingDone occur: if the text is still empty it is restored from the saved datum, and the text value, either new or restored, is copied to the Edit2 control.

The QUIT button closes the program.

The EditingDone or Exit actions occur for Edit1 when the user clicks on the form field or on the Edit2 control, but the actions do not occur when the TButton or TRadioButton is clicked, indicating that Edit1 has not lost focus.

I suggest there could be an option for TEdit to either lose or regain focus when any kind of button is used.

unit Unit1;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, Forms, Controls, Graphics,
  Dialogs, StdCtrls;
type
  TForm1 = class(TForm)
    Button1: TButton;
    ButtonQuit: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    RadioButton1: TRadioButton;
  procedure ButtonQuitClick(Sender: TObject);
  procedure Edit1Click(Sender: TObject);
  procedure Edit1EditingDone(Sender: TObject);
  procedure Edit1Exit(Sender: TObject);
  private
  public
end;

var
  Form1: TForm1;

implementation
{$R *.lfm}
var  saveEdit :shortstring;

procedure updateEdit2;
begin
     Form1.Edit2.Text := Form1.Edit1.Text;
end;

procedure TForm1.ButtonQuitClick(Sender: TObject);
begin
    Close;
end;

procedure TForm1.Edit1Click(Sender: TObject);
begin
    saveEdit := Edit1.Text;
    Edit1.Text := '';
end;

procedure TForm1.Edit1EditingDone(Sender: TObject);
begin
    if Edit1.Text = '' then Edit1.Text := saveEdit;
    updateEdit2;
end;

procedure TForm1.Edit1Exit(Sender: TObject);
begin
    Edit1EditingDone(Sender);
end;

end.

object Form1: TForm1
  Left = 766
  Height = 319
  Top = 385
  Width = 371
  Caption = 'Form1'
  ClientHeight = 319
  ClientWidth = 371
  LCLVersion = '1.2.6.0'
  object Edit1: TEdit
    Left = 162
    Height = 22
    Top = 55
    Width = 44
    OnClick = Edit1Click
    OnEditingDone = Edit1EditingDone
    OnExit = Edit1Exit
    TabOrder = 0
    Text = 'X'
  end
  object Edit2: TEdit
    Left = 162
    Height = 22
    Top = 90
    Width = 44
    TabOrder = 1
  end
  object Button1: TButton
    Left = 162
    Height = 25
    Top = 144
    Width = 75
    Caption = 'Button 1'
    TabOrder = 2
  end
  object ButtonQuit: TButton
    Left = 162
    Height = 25
    Top = 225
    Width = 75
    Caption = 'QUIT'
    OnClick = ButtonQuitClick
    TabOrder = 3
  end
  object RadioButton1: TRadioButton
    Left = 138
    Height = 18
    Top = 183
    Width = 68
    Caption = 'Radio 1'
    TabOrder = 4
  end
  object Label1: TLabel
    Left = 90
    Height = 16
    Top = 57
    Width = 36
    Caption = 'Edit 1'
    ParentColor = False
  end
  object Label2: TLabel
    Left = 90
    Height = 16
    Top = 93
    Width = 36
    Caption = 'Edit 2'
    ParentColor = False
  end
end
« Last Edit: April 10, 2015, 01:43:52 pm by lor »

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1260
G'day,

This doesn't sound like expected behaviour to me.  Either you've found a bug, or you're not doing something correct.

Try to reduce your code to a simple test case that reproduces the issue, then post the code here.  Others will likely attempt to run your code and let you know if it's your code or LCL code that's at fault.

Also, please remember that the code you're running will change depending on platform, and depending on what version of the LCL you're running.  You will need to let us know these details as well.

If it turns out to be a bug in the LCL, then please read this;
http://wiki.lazarus.freepascal.org/How_do_I_create_a_bug_report

Our bugtracker is at:
http://bugs.freepascal.org/view_all_bug_page.php?project_id=1

In fact, looking in there, what you post sounds suspiciously like:
http://bugs.freepascal.org/view.php?id=20057

In which case, the issue just well may be resolved in the trunk version of the code base.  Trunk is the latest development version, I'm guessing you're running an older stable release...

Which raises your next question ;-)  How do I get Trunk?

There are two known easy ways, and the official harder way.  Google (or search these forums) for fpcup and getlazarus for the easy two :-)
Lazarus Trunk/FPC Trunk on Windows [7, 10]
  Have you tried searching this forum or the wiki?:   http://wiki.lazarus.freepascal.org/Alternative_Main_Page
  BOOKS! (Free and otherwise): http://wiki.lazarus.freepascal.org/Pascal_and_Lazarus_Books_and_Magazines

lor

  • New Member
  • *
  • Posts: 26
Thanks. I'll put something together and edit my query. I am using the current distribution versions. The bug you mentioned is similar, but only addresses the use of the Return key. I think I've found a bug, having tried many ways with extra code to trap or detect the situation.

I can understand that some applications would not want the text editing to be terminated while the user presses some kind of button as part of the edit (copy something, etc.), but that should be a controllable option I would think.

--Lor

zeljko

  • Hero Member
  • *****
  • Posts: 1596
    • http://wiki.lazarus.freepascal.org/User:Zeljan
When a TButton or TRadioButton control is clicked, the previously changed TEdit control .OnExit or .EditingDone actions do not occur. They do occur if another TEdit control is entered, however. How can I change this behavior so that the TEdit controls get exit and/or done actions activated when a button os pushed? I'd rather not have to monitor edit fields and change the entry of every button to call the edit control exit actions. Thanks for enlightening me!

If your button is TSpeedButton then it's obvious that OnExit won't trigger, since TEdit is still focused. If you clicked eg TBitBtn (and it takes focus) and TEdit.OnExit does not trigger then it's bug. What lazarus version do you use ? Operating system ? Widgetset ?

lor

  • New Member
  • *
  • Posts: 26
Please see additions to the original post.

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1260
If I'm understanding you correctly, then this issue is resolved in Trunk already. 

I'm running Windows 7, SVN48027, win32/win64.  I did wonder if Bart's patch in http://bugs.freepascal.org/view.php?id=20057 would also fix this issue.

Running your code, if I make a change in Edit1, then click either the Tbutton or TRadioButton, my changes are immediately copied to the second Edit2.

There is currently a release candidate for the next version of Lazarus.  Looking at the timings, this should have issue 20057 resolved in it.   You can either try the RC, or wait until 1.4 is formally released...

Quote
Lazarus 1.2.6  FPC 2.6.4  Mac OSX 8.5  i386-darwin-carbon

Ahh.  We need someone else on that operating system to double check.  Might be working under windows only...
« Last Edit: April 03, 2015, 08:21:46 pm by Mike.Cornflake »
Lazarus Trunk/FPC Trunk on Windows [7, 10]
  Have you tried searching this forum or the wiki?:   http://wiki.lazarus.freepascal.org/Alternative_Main_Page
  BOOKS! (Free and otherwise): http://wiki.lazarus.freepascal.org/Pascal_and_Lazarus_Books_and_Magazines

lor

  • New Member
  • *
  • Posts: 26
Many thanks for taking the time to check into this.  I will wait for someone on Mac to verify if the newer version fixes it.

lor

  • New Member
  • *
  • Posts: 26
Please see my workaround placed at the top of the original post.

 

TinyPortal © 2005-2018