Recent

Author Topic: Checkbox OnClick disallows the ability to change checked propertry via buttons  (Read 1493 times)

dox

  • Newbie
  • Posts: 3
Hey, newbie to Lazarus, so I'm sure there is some logical reason for this and sort of visioned a workaround; but this leaves me puzzled

As i'm new to Lazarus, touched Delphi once and have only used Pascal as college programming. I am confused to why if I setup a click event I am no longer able control the checkbox via the form buttons

I have my form, two buttons and a checkbox.

The stop button, unticks the box, the start button ticks the checkbox - This works greatly.
Now I wish to make this checkbox untickable via clicking on it.

I could set the enabled property to false -- but this turns it grey. Button events still work

So, if I create an "OnClick" event for the CheckBox, and tell it to set the checked property to False.

Code: Pascal  [Select][+][-]
  1. procedure Tfrm_ServControl.chk_ServStatusClick(Sender: TObject);
  2. begin
  3.   chk_ServStatus.Checked := False;
  4. end;

The checkbox is now untickable, great. But now the Start and Stop Button's can't interact with it.

Why would this be? I thought events were exclusive to the elements and this would react to only "OnClick" of the checkbox, and not the buttons. Meaning the buttons should still be able to change the property of OnClick accordingly.

Many thanks
-dox
« Last Edit: July 17, 2024, 11:01:14 pm by dox »

jamie

  • Hero Member
  • *****
  • Posts: 6734
You maybe causing a loop in the event.

Use the TAG property of the control.

Upon entry of the event, Test it

IF Tag <> 0 Then exit else TAG  := 1;

do you code..

Tag := 0;


This way, if you cause the event to get retriggered while in there, you can reject it.
The only true wisdom is knowing you know nothing

dox

  • Newbie
  • Posts: 3
Thanks for the reply, but huh?
That was my vision to setup a conditional, global variable and register against that but still leaves me perplexed to why an OnClick for that checkbox becomes uncontrollable via the buttons when you define it as False for OnClick.

My newbie code:

Code: Pascal  [Select][+][-]
  1. procedure Tfrm_ServControl.btn_ServStartClick(Sender: TObject);
  2. begin
  3.   chk_ServStatus.Checked := True;
  4.   lbl_ServStatus.Caption := 'Server is online';
  5. end;
  6.  
  7. procedure Tfrm_ServControl.btn_ServStopClick(Sender: TObject);
  8. begin
  9.    if chk_ServStatus.Checked  = True then
  10.    begin
  11.       chk_ServStatus.Checked := False;
  12.       lbl_ServStatus.Caption := 'Server is offline';
  13.    end
  14. end;
  15.  
  16. procedure Tfrm_ServControl.chk_ServStatusClick(Sender: TObject);
  17. begin
  18.   chk_ServStatus.Checked := False;
  19. end;

Edit:
The example you gave didn't work either.
« Last Edit: July 18, 2024, 03:28:19 am by dox »

Handoko

  • Hero Member
  • *****
  • Posts: 5376
  • My goal: build my own game engine using Lazarus
How about this:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     btnStop: TButton;
  16.     btnStart: TButton;
  17.     CheckBox1: TCheckBox;
  18.     procedure btnStartClick(Sender: TObject);
  19.     procedure btnStopClick(Sender: TObject);
  20.     procedure CheckBox1Change(Sender: TObject);
  21.     procedure FormCreate(Sender: TObject);
  22.   private
  23.     FRunning: Boolean;
  24.     procedure UpdateCheckBoxStatus;
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.  
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34. { TForm1 }
  35.  
  36. procedure TForm1.btnStopClick(Sender: TObject);
  37. begin
  38.   FRunning := False;
  39.   UpdateCheckBoxStatus;
  40. end;
  41.  
  42. procedure TForm1.CheckBox1Change(Sender: TObject);
  43. begin
  44.   UpdateCheckBoxStatus;
  45. end;
  46.  
  47. procedure TForm1.btnStartClick(Sender: TObject);
  48. begin
  49.   FRunning := True;
  50.   UpdateCheckBoxStatus;
  51. end;
  52.  
  53. procedure TForm1.FormCreate(Sender: TObject);
  54. begin
  55.   FRunning := False;
  56. end;
  57.  
  58. procedure TForm1.UpdateCheckBoxStatus;
  59. begin
  60.   CheckBox1.Checked := FRunning;
  61. end;
  62.  
  63. end.

wp

  • Hero Member
  • *****
  • Posts: 12458
Now I wish to make this checkbox untickable via clicking on it.
Why do you use a checkbox then? A checkbox is an interactive control meant to be switched by the user. Just for display purposes, you could use a simple TLabel or TStaticText instead.

If you insist on the checkbox you could try the TCheckboxEx in the ExCtrls package (https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/exctrls/, https://wiki.freepascal.org/ExCtrls#TRadioButtonEx,_TCheckBoxEx,_TRadioGroupEx_and_TCheckGroupEx); or you could use the TOnOffSwitch from the Industrial package which you can install via Online-Package-Manager (https://wiki.freepascal.org/Industrial#TOnOffSwitch). Both of them have a ReadOnly property by means of which you can inhibit user interaction without switching the control color to gray. There are certainly more components of this kind in other component collections.

Zvoni

  • Hero Member
  • *****
  • Posts: 2737
Or you assign one and the same procedure to all 3 events, and check the Sender-Object
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  5. type
  6.   TForm1 = class(TForm)
  7.     btnStart: TButton;
  8.     btnStop: TButton;
  9.     chkServer: TCheckBox;
  10.     procedure OnClick(Sender: TObject);
  11.   end;
  12. var
  13.   Form1: TForm1;
  14. implementation
  15. {$R *.lfm}
  16. procedure TForm1.OnClick(Sender: TObject);
  17. begin
  18.   If Sender Is TButton Then
  19.     Begin
  20.        If TButton(Sender).Name='btnStart' Then
  21.          Begin
  22.            chkServer.Tag:=1;
  23.            chkServer.Checked:=True;
  24.          end
  25.        Else
  26.          Begin
  27.            chkServer.Tag:=0;
  28.            chkServer.Checked:=False;
  29.          end;
  30.     end
  31.   Else
  32.     Begin
  33.       if chkServer.Tag=0 Then chkServer.Checked:=False Else chkServer.Checked:=True;
  34.     end;
  35. end;
  36.  
  37. end.
  38.  

With this the checkbox can only be checked/unchecked via the Buttons.
No need for additional Properties or variables

EDIT:
Even shorter.
Set the Tag of btnStart to 1, Tag of btnStop to 0
Code: Pascal  [Select][+][-]
  1. procedure TForm1.OnClick(Sender: TObject);
  2. begin
  3.   If Sender Is TButton Then
  4.     Begin
  5.        chkServer.Tag:=TButton(Sender).Tag;
  6.        chkServer.Checked:=TButton(Sender).Tag.ToBoolean;
  7.     end
  8.   Else chkServer.Checked:=chkServer.Tag.ToBoolean;
  9. end;                      

EDIT2: Since you have something with StartServer and StopServer in your naming-convention:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.OnClick(Sender: TObject);
  2. begin
  3.   If Sender Is TButton Then
  4.     Begin
  5.        If TButton(Sender).Tag.ToBoolean Then
  6.          Begin
  7.             //Insert Code to start this "Server", maybe even check if server is already running
  8.             //If start of Server successful then
  9.             chkServer.Tag:=1;
  10.             //Else
  11.             //chkServer.Tag:=0;
  12.          end
  13.        Else
  14.          Begin
  15.            //Insert code to stop this "Server"
  16.            //If stop of Server successful then
  17.            chkServer.Tag:=0;
  18.            //Else
  19.            //chkServer.Tag:=1;
  20.          end;
  21.     end;
  22.   chkServer.Checked:=chkServer.Tag.ToBoolean;
  23. end;                                                    

EDIT3: Just saw wp referring to industrial package.
An alternative to a CheckBox might be to use the LED-Control or that Traffic-Light-Control from industrial
« Last Edit: July 18, 2024, 01:39:59 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

dox

  • Newbie
  • Posts: 3
Why do you use a checkbox then? A checkbox is an interactive control meant to be switched by the user. Just for display purposes, you could use a simple TLabel or TStaticText instead.

First time in ever using Lazarus. Still learning the ropes. I thought using a ticked checkbox to indicate the status was a neat idea.
I'm not looking for a label, I have one of those, I was looking for visual representation that indicates status.
A checkbox does that. Ticked for on, unticked for off -- you couldn't get any simpler. I just didn't want it to be tickable by mouseclick. Even if it's designed to be.

Quote
If you insist on the checkbox you could try the TCheckboxEx in the ExCtrls package (https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/exctrls/, https://wiki.freepascal.org/ExCtrls#TRadioButtonEx,_TCheckBoxEx,_TRadioGroupEx_and_TCheckGroupEx); or you could use the TOnOffSwitch from the Industrial package which you can install via Online-Package-Manager (https://wiki.freepascal.org/Industrial#TOnOffSwitch). Both of them have a ReadOnly property by means of which you can inhibit user interaction without switching the control color to gray. There are certainly more components of this kind in other component collections.

Thanks for the recommendation, I'll give this a checkout. I was just trying to be simple without having to install any other additional packages.


@ Handoko, and everyone else, many thanks every else for your examples. I'll get them shot.
« Last Edit: July 18, 2024, 02:58:52 pm by dox »

Zvoni

  • Hero Member
  • *****
  • Posts: 2737
First time in ever using Lazarus. Still learning the ropes.
If you need help, how to assign one and the same Procedure to all 3 events, give a shout

A checkbox does that. Ticked for on, unticked for off -- you couldn't get any simpler. I just didn't want it to be tickable by mouseclick. Even if it's designed to be.
TPanel maybe?
BackColor:=clGreen, BackColor:=clRed
« Last Edit: July 18, 2024, 03:09:12 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

wp

  • Hero Member
  • *****
  • Posts: 12458
I thought using a ticked checkbox to indicate the status was a neat idea.
I'm not looking for a label, I have one of those, I was looking for visual representation that indicates status.
A checkbox does that. Ticked for on, unticked for off -- you couldn't get any simpler. I just didn't want it to be tickable by mouseclick. Even if it's designed to be.
Or you could use a TImage into which you load checked and unchecked images (this is easy since the TImage of Laz3.0x supports an ImageList) and a label with corresponding message texts. See attached project.

jamie

  • Hero Member
  • *****
  • Posts: 6734
use speedbuttons and assign the correct icon to it to set the state from an imagelist.
The only true wisdom is knowing you know nothing

tetrastes

  • Hero Member
  • *****
  • Posts: 591
So, if I create an "OnClick" event for the CheckBox, and tell it to set the checked property to False.

The checkbox is now untickable, great. But now the Start and Stop Button's can't interact with it.

Why would this be? I thought events were exclusive to the elements and this would react to only "OnClick" of the checkbox, and not the buttons. Meaning the buttons should still be able to change the property of OnClick accordingly.

Your buttons change the Checked property of TCheckBox, but this is not simply changing a boolean variable, because you need to change visual representation of CheckBox control at the same time. So there is much code is executed, and among others is CheckBox's OnClick event handler, if it is assigned.

 

TinyPortal © 2005-2018