Recent

Author Topic: [Solved] Draw (Paint?) RadioGroup items - different colors for different items  (Read 2421 times)

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
How can I draw the various items in a TRadioGroup. In particular, I want to show different items in different colors. Better yet, use multiple colors for the same item.
« Last Edit: July 31, 2019, 12:12:23 am by bobonwhidbey »
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

reb

  • New member
  • *
  • Posts: 8
There are 2 color properties you can edit:
RadioGroup1.Controls[1].Color:=clGreen; sets the highlight and selection color
RadioGroup1.Controls[1].Font.Color:=clPurple; sets the font color of the text

wp

  • Hero Member
  • *****
  • Posts: 11916
The Font.Color of TRadioButton (which is used internally inside a TRadioGroup) is drawn by the widgetset and is often out of control for the programmer. In themed Windows, for example, you cannot change TRadioButton.Font.Color. Search in the forum - there was a recent discussion about this issue.

What you can do is to look for an owner-drawn RadioButton, e.g. the TplRadioButton from the package pl_excontrols which you can install via Online-Package-Manager (the button symbol is a bit smaller, though, I don't know if there is a way to increase it to the normal height). Probably there are other packages around out there which do it better.

You can combine these individual RadioButtons inside a TGroupbox and get the same appearance as a TRadioGroup.

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
WP - this is what I've done but I've had a problem. Inside a GroupBox I placed 4 RadioButtons and beside each RadioButton I placed a TLabel. My problem is - When I click a label I can get the corresponding event to occur but I can not get the appropriate button to appear clicked (down/black). Seems like a simple programming task that has eluded me.

I want the button to be "clicked" when the user clicks the tlabel. Of course each label has it's tag equal to the tag of the corresponding RadioButton.

Code: Pascal  [Select][+][-]
  1. procedure TMyApp.LabelClick(Sender: TObject); // each Label has this click event
  2. begin
  3.   if Sender is TLabel then
  4.     with Sender as TLabel do
  5.       case tag of
  6.         0: RBClick(RBC); // RBC, RBD, RBH, and RBS are the names of the RadioButton components
  7.         1: RBClick(RBD);
  8.         2: RBClick(RBH);
  9.         else
  10.           RBClick(RBS);
  11.       end;
  12. end;
  13.  
  14. procedure TMyApp.RBClick(Sender: TObject);   // each RadioButton has this click event
  15. begin
  16.   GroupBox.Tag := TRadioButton(Sender).Tag;
  17.   TRadioButton(Sender).Refresh;
  18.   DoDesiredEvent;
  19. end;
  20.  
  21.  
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

wp

  • Hero Member
  • *****
  • Posts: 11916
Why don't you use the "Caption" of the RadioButton to provide the description of the radiobutton? An extra label is not needed.

------------------

The label has a property FocusControl in which you can select the control which is focused when the label is clicked. I could swear that I had used this feature in several projects. But now I checked it again and found out that -- it does not work, at least not for a click; it does work, however, for the keyboard when a hotkey is assigned to the label using the Ampersand character - but this is probably not what you want.

But of course you can write code to "click" the radiobutton by means of the label. I would do it differently, though, because the FocusControl can be used for exactly this purpose:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Label1Click(Sender: TObject);
  2. var
  3.   lbl: TLabel;
  4.   rb: TRadioButton;
  5. begin
  6.   if not (Sender is TLabel) then
  7.     exit;
  8.   lbl := TLabel(Sender);
  9.   if lbl.FocusControl is TRadioButton then begin
  10.     rb := TRadioButton(lbl.FocusControl);
  11.     rb.Checked := not rb.Checked;
  12.     rb.SetFocus;
  13.   end;
  14. end;

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
The reason I used a separate label is because I wanted to be able to draw it myself - different colors for different text would be nice. On the TRadioButton the Font.Size, Font.Name, and Font.Style all seem to work, but the Font.Color does not.  Like the old Model T Fords, you can get them in any color so long as it's black!

I would prefer to use the RadioButton's label, but I need some color.
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Try this; it may work better:
Code: Pascal  [Select][+][-]
  1. procedure TMyApp.LabelClick(Sender: TObject); // each Label has this click event
  2. begin
  3.   if Sender is TLabel then
  4.     with Sender as TLabel do
  5.       case tag of
  6.         0: RBC.Click; // RBC, RBD, RBH, and RBS are the names of the RadioButton components
  7.         1: RBD.Click;
  8.         2: RBH.Click;
  9.         else
  10.           RBS.Click;
  11.       end;
  12. end;

Note that I've not tested it; it's just a "maybe ..."

If that doesn't work; All your code does is just call another procedure in your code which doesn't affect the state of the controls.

As a minimum then your LabelClick handler should set the Checked property of the correspondign radio button before calling the OnClick handler for the radio buttons.

Essentially, what you must do is mimic the effect a real click on the radio button would have.
« Last Edit: July 30, 2019, 11:24:49 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
This did not work. The desired event was triggered but the "button" didnt get "pushed".

Code: Pascal  [Select][+][-]
  1.     with Sender as TLabel do
  2.       case tag of
  3.         0: RBC.OnClick(RBC);
  4.         1: RBD.OnClick(RBD);
  5.         2: RBH.OnClick(RBH);
  6.         else
  7.           RBS.OnClick(RBS);
  8.       end;  

It seems like the most straight-forward approach would be to use a separate TRadoButton, as WP suggested, but the Font.Color doesn't work. I think I'm looking for a way to override that problem.
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Did you try the code I actually posted? That was calling the Click method of the radio button, not the OnClick:

Code: Pascal  [Select][+][-]
  1.     with Sender as TLabel do
  2.       case tag of
  3.         0: RBC.Click;
  4.         1: RBD.Click;
  5.         2: RBH.Click;
  6.         else
  7.           RBS.Click;
  8.       end;  

You may have to add a "phantom" interposed TRadioButton class---IIRC the Click method is protected in that class.

But if it doesn't work, just do this:
Code: Pascal  [Select][+][-]
  1. procedure TMyApp.LabelClick(Sender: TObject); // each Label has this click event
  2. var
  3.   TheButton: TRadioButton
  4. begin
  5.   if Sender is TLabel then begin
  6.     with Sender as TLabel do
  7.       case tag of
  8.         0: TheButton := RBC;
  9.         1: TheButton := RBD;
  10.         2: TheButton := RBH;
  11.         else
  12.           TheButton := RBS;
  13.       end;
  14.     TheButton.Checked := True;
  15.     RBClick(TheButton);
  16.   end;
  17. end;
« Last Edit: July 30, 2019, 11:50:40 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
Thanks lucamar. That approach worked perfectly. Yes, originally I had tried RHB.Click, which didn't work.

That RBClick(TheButton); statement is redundant because it is called by dint of the TheButton.Checked := True; statement. Some users may want to force that call, even when the radiobutton is already down (already checked).

Thank you.
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Draw (Paint?) RadioGroup items - different colors for different items
« Reply #10 on: July 31, 2019, 12:01:55 pm »
That RBClick(TheButton); statement is redundant because it is called by dint of the TheButton.Checked := True; statement. Some users may want to force that call, even when the radiobutton is already down (already checked).

That's good to know, thanks; archived in my "Controls' caveats" DB :)

The full code then is something like:
Code: Pascal  [Select][+][-]
  1. procedure TMyApp.LabelClick(Sender: TObject); // each Label has this click event
  2. var
  3.   TheButton: TRadioButton
  4. begin
  5.   if Sender is TLabel then begin
  6.     case TLabel(Sender).tag of
  7.       0: TheButton := RBC;
  8.       1: TheButton := RBD;
  9.       2: TheButton := RBH;
  10.       else
  11.         TheButton := RBS;
  12.     end;
  13.     if TheButton.Checked then
  14.       RBClick(TheButton) {if already checked just call the handler}
  15.     else
  16.       TheButton.Checked := True; {Tick it; the handler is called automagically}
  17.   end;
  18. end;
Is that it?
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
I think the programer knows whether or not he wants to process all the code triggered by the Click event. In my case, it's a lot of code that I'd rather not repeat. One thing I learned in this exercise is that that RadioButton's OnClick event is triggered when a button is turned ON. If the button is already ON the code is not triggered just be setting Checked to True  (since it was already True).

Since I prefer "terse" code, my entire LabelClick event looks like this:
Code: Pascal  [Select][+][-]
  1. begin
  2.   with Sender as TLabel do
  3.     case tag of
  4.       0: RBC.Checked := True;
  5.       1: RBD.Checked := True;
  6.       2: RBH.Checked := True;
  7.       else
  8.         RBS.Checked := True;
  9.     end;
  10. end;
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

 

TinyPortal © 2005-2018