Recent

Author Topic: [SOLVED] | with Sender as [Thing] do | Me being stupid again.  (Read 7684 times)

MorbidFractal

  • Jr. Member
  • **
  • Posts: 97
[SOLVED] | with Sender as [Thing] do | Me being stupid again.
« on: February 21, 2016, 05:19:38 am »
Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ButtonClick(Sender: TObject);
  2. begin
  3.   with Sender as TButton do
  4.   begin
  5.     case Name of
  6.     'Button01': PrjIndex := 0;
  7.     'Button02': if PrjIndex <> 0 then
  8.                 PrjIndex := DBUnit00.RecordRemove('F00', PrjIndex);
  9.     'Button03': if (PrjIndex <> 0) and (Validate() = True) then
  10.                 PrjIndex := DBUnit00.RecordUpdate('F00', PrjIndex);
  11.     'Button04': if (PrjIndex <> 0) and (Validate() = True) then
  12.                 PrjIndex := DBUnit00.RecordCommit('F00', PrjIndex);
  13.     'Button05': PrjIndex := DBUnit00.RecordReload('F00', PrjIndex);
  14.     end;
  15.     if Name = 'Button06' then SPKUnit00.CalcEnds() else LoadAll();
  16.   end;
  17. end;  

The above works...

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   with Sender as TComboBox do
  4.   begin
  5.     case Name of
  6.     'ComboBox01':if ItemIndex = -1 then ItemIndex := PrjIndex else
  7.       begin
  8.       end;
  9.     'ComboBox02':if ItemIndex = -1 then ItemIndex := HubIndex else
  10.       begin
  11.       end;
  12.     'ComboBox03':if ItemIndex = -1 then ItemIndex := RimIndex else
  13.       begin
  14.       end;
  15.     'ComboBox04':if ItemIndex = -1 then ItemIndex := SpkIndex else
  16.       begin
  17.       end;
  18.     end;
  19.   end;
  20. //if ComboBox01.ItemIndex = -1 then ComboBox01.ItemIndex := PrjIndex;
  21. //PrjIndex := ComboBox01.ItemIndex;
  22. //LoadDat();
  23. //SVGUnit00.LoadSVG('pics/logo.svg');
  24. end;          

The above throws a SIGSEGV Error on 5: case Name of'.

My, lack of, experience is that SIGSEGV occurs when you try to reference something that does not exist or does not exist yet..

If I change the above example to,

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   with Sender as TButton do
  4.   begin
  5.     case Name of
  6.     'ComboBox01':if ItemIndex = -1 then ItemIndex := PrjIndex else
  7.       begin
  8.       end;
  9.     'ComboBox02':if ItemIndex = -1 then ItemIndex := HubIndex else
  10.       begin
  11.       end;
  12.     'ComboBox03':if ItemIndex = -1 then ItemIndex := RimIndex else
  13.       begin
  14.       end;
  15.     'ComboBox04':if ItemIndex = -1 then ItemIndex := SpkIndex else
  16.       begin
  17.       end;
  18.     end;
  19.   end;
  20. //if ComboBox01.ItemIndex = -1 then ComboBox01.ItemIndex := PrjIndex;
  21. //PrjIndex := ComboBox01.ItemIndex;
  22. //LoadDat();
  23. //SVGUnit00.LoadSVG('pics/logo.svg');
  24. end;

Using [Thing] as TButton instead of TComboBox then the SIGSEGV error goes away but a TButton does not have an ItemIndex so it falls over with 6: Error: Identifier not found "ItemIndex"

1.4RC3
2.6.4
Linux Mint

Any Ideas?
« Last Edit: February 21, 2016, 05:35:49 pm by MorbidFractal »

MorbidFractal

  • Jr. Member
  • **
  • Posts: 97
Re: with Sender as [Thing] do
« Reply #1 on: February 21, 2016, 06:02:26 am »
Hmmm..

http://forum.lazarus.freepascal.org/index.php/topic,31558.0.html

Cute... so,

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   case (Sender as TComboBox).Name of
  4.   'ComboBox01':if ItemIndex = -1 then ItemIndex := PrjIndex else
  5.     begin
  6.     end;
  7.   'ComboBox02':if ItemIndex = -1 then ItemIndex := HubIndex else
  8.     begin
  9.     end;
  10.   'ComboBox03':if ItemIndex = -1 then ItemIndex := RimIndex else
  11.     begin
  12.     end;
  13.   'ComboBox04':if ItemIndex = -1 then ItemIndex := SpkIndex else
  14.     begin
  15.     end;
  16.   end;
  17. end;

Still falls over on 4:Error: Identifier not found "ItemIndex"

FTurtle

  • Sr. Member
  • ****
  • Posts: 292
Re: with Sender as [Thing] do
« Reply #2 on: February 21, 2016, 06:06:27 am »
Quote
The above throws a SIGSEGV Error on 5: case Name of'.

Looks like TFrame00.ComboBoxChanged called before frame was created.
Try this:

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   ShowMessage((Self as TFrame).Name);
  4. end;

If you will not get error, this suppose is wrong.

FTurtle

  • Sr. Member
  • ****
  • Posts: 292
Re: with Sender as [Thing] do
« Reply #3 on: February 21, 2016, 06:12:25 am »
Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   case (Sender as TComboBox).Name of
  4.   'ComboBox01':if ItemIndex = -1 then ItemIndex := PrjIndex else
  5.     begin
  6.     end;
  7. ...
  8.  
Still falls over on 4:Error: Identifier not found "ItemIndex"

You forgot with

MorbidFractal

  • Jr. Member
  • **
  • Posts: 97
Re: with Sender as [Thing] do
« Reply #4 on: February 21, 2016, 06:23:26 am »
Thanks for the reply...

Using your method from the other thread it seems to know it is there.. and previously it did as well when I called it something else because it stopped giving the SIGSEGV.

With your previous suggestion... Attached, but it still does not know about ItemIndex.

I note your later comment about 'with' but I am unsure as to where to put a 'with'.

FTurtle

  • Sr. Member
  • ****
  • Posts: 292
Re: with Sender as [Thing] do
« Reply #5 on: February 21, 2016, 06:38:54 am »
Quote
I note your later comment about 'with' but I am unsure as to where to put a 'with'.

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   with (Sender as TComboBox) do
  4.   case Name of
  5.   'ComboBox01':if ItemIndex = -1 then ItemIndex := PrjIndex else
  6.     begin
  7.     end;
  8. ...

FTurtle

  • Sr. Member
  • ****
  • Posts: 292
Re: with Sender as [Thing] do
« Reply #6 on: February 21, 2016, 06:47:59 am »
By the way.
In other thread author need one event handler for few buttons because there are few buttons (digits) which should be similarly processed.
In your case, this is not necessary.
It is better to make separate handlers for each combobox.

MorbidFractal

  • Jr. Member
  • **
  • Posts: 97
Re: with Sender as [Thing] do
« Reply #7 on: February 21, 2016, 07:00:03 am »
Quote
I note your later comment about 'with' but I am unsure as to where to put a 'with'.

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   with (Sender as TComboBox) do
  4.   case Name of
  5.   'ComboBox01':if ItemIndex = -1 then ItemIndex := PrjIndex else
  6.     begin
  7.     end;
  8. ...

I think that almost reduces to what I had in the first place.... give or take a begin end;

By the way.
In other thread author need one event handler for few buttons because there are few buttons (digits) which should be similarly processed.
In your case, this is not necessary.
It is better to make separate handlers for each combobox.

Point taken but, if it would work, there is a certain 'elegance' to having control actions handled by one procedure even if those actions differ slightly.

I seem to have hit an impasse so it is probably 'Pot Noodle' time followed by bed.

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1263
Re: with Sender as [Thing] do
« Reply #8 on: February 21, 2016, 08:55:57 am »
I agree, the code sample above appears to be functionally identical to the initial code.

I honestly can't see anything wrong with the original code, other than it breaks one of my personal cardinal rules.  Never use With. 

The line "Case Name Of" demonstrates my issue.  This code is inside TFrame00, yet is part of a With.  Which Name precisely should the compiler choose. TFrame00.Name or (Sender as TComboBox).Name.  Or some other variable you've got floating around.

I'm not suggesting that the with is your issue, but it needs to be ruled out.  Can you try the following code, see if that works?

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. Var
  3.   x : TComboBox;
  4. begin
  5.   If (Sender Is TComboBox) Then
  6.   begin
  7.   x := (Sender As TComboBox);
  8.  
  9.     case x.Name of
  10.     'ComboBox01':if x.ItemIndex = -1 then x.ItemIndex := PrjIndex else
  11.       begin
  12.       end;
  13.     'ComboBox02':if x.ItemIndex = -1 then x.ItemIndex := HubIndex else
  14.       begin
  15.       end;
  16.     'ComboBox03':if x.ItemIndex = -1 then x.ItemIndex := RimIndex else
  17.       begin
  18.       end;
  19.     'ComboBox04':if x.ItemIndex = -1 then x.ItemIndex := SpkIndex else
  20.       begin
  21.       end;
  22.     end;
  23.   End;
  24. end;  
  25.  

I suspect that if it runs, then the above code will also raise a Exception, in which case there is something wrong with your code elsewhere.

If on the other hand, this code doesn't run, then that defensive "If (Sender Is TComboBox) Then" that I've thrown in at the start has found at least one issue.  Sender in this routine is probably Nil, and I don't know why.  Again, need to see more of your code.

Sleep well :-)
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

Thaddy

  • Hero Member
  • *****
  • Posts: 16813
  • Ceterum censeo Trump esse delendam
Re: with Sender as [Thing] do
« Reply #9 on: February 21, 2016, 08:58:03 am »
It is better to make separate handlers for each combobox.
Why? How? Qualify? That looks like you are stuck with what the IDE does for you, click and create a handler. That's not always proper. Not at all.
That only means fragmented and difficult to maintain code. It is often better to have one central place to handle similar code.
What IS definitely better is take the time to give your controls a meaningful name instead of 'ComboBox0X' because that will make your code readable.
And I strongly object to using case with strings. Always have ;) Just because it is implemented doesn't mean you have to use it >:D
« Last Edit: February 21, 2016, 08:59:46 am by Thaddy »
Changing servers. thaddy.com may be temporary unreachable but restored when the domain name transfer is done.

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1263
Re: with Sender as [Thing] do
« Reply #10 on: February 21, 2016, 09:10:59 am »
Something Thaddy has said has just made me realise something.  Where you build your 4 Index variables, instead write the value to the associated combobox tag value.

Then you can use the one procedure, and it simply becomes

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   If (Sender Is TComboBox) Then
  4.   begin
  5.     (Sender As TComboBox).itemIndex := (Sender As TComboBox).Tag;
  6.   end;
  7. end;  
  8.  

No need for case with String (Thaddy didn't tell you why not to use it, it's slow as are all string comparisons.  For your case you won't notice, but getting out of the habit is a good one :-) )

Uses a single event handler.  But I suspect you were using only one anyway looking at it's name.

And of course, if my suspicion that the error is elsewhere bears fruit, the code I've shared here will still raise issues :-(

EDIT: very mild optimisation below seeing as we're now called IS

Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   If (Sender Is TComboBox) Then
  4.   begin
  5.     TComboBox(Sender).itemIndex := TComboBox(Sender).Tag;
  6.   end;
  7. end;  
  8.  

I forgot that AS does an If IS anyway...
« Last Edit: February 21, 2016, 09:13:55 am 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

Thaddy

  • Hero Member
  • *****
  • Posts: 16813
  • Ceterum censeo Trump esse delendam
Re: with Sender as [Thing] do
« Reply #11 on: February 21, 2016, 10:24:21 am »
Of course the ideal situation would be if instance pointers could be used as an ordinal type.
Then you could write code like this ;) :
Code: Pascal  [Select][+][-]
  1. procedure TFrame00.ComboBoxChanged(Sender: TObject);
  2. begin
  3.   If Sender Is TComboBox Then
  4.   case TCombobox(sender) of
  5.     Combobox1:;
  6.     ComboBox2:;
  7.     ComboBox3:;
  8.   end;
  9. end;  
  10.  

I think I turn that into a feature request :) [edit] Put it on devel list.
« Last Edit: February 21, 2016, 11:45:05 am by Thaddy »
Changing servers. thaddy.com may be temporary unreachable but restored when the domain name transfer is done.

FTurtle

  • Sr. Member
  • ****
  • Posts: 292
Re: with Sender as [Thing] do
« Reply #12 on: February 21, 2016, 03:14:34 pm »
I think the problem refers to use of TFrame.
Add to frame (not to form) new TEdit for test and try this code:

Code: Pascal  [Select][+][-]
  1. procedure TFrame1.ComboBox01Change(Sender: TObject);
  2. begin
  3.   Edit1.Text := IntToStr(Integer(Pointer(Sender))) +': '+ TComboBox(Sender).Name;
  4. end;
  5.  

What you get?

MorbidFractal

  • Jr. Member
  • **
  • Posts: 97
Re: with Sender as [Thing] do
« Reply #13 on: February 21, 2016, 03:23:18 pm »
Hi Again, Yawn. Thanks for the extra hints.

Mr Cornflakes suggestion, Protective If, seems to hint at something going wrong. Result with breakpoint to check attached.. F7 and it bounces over the code to the final end so it would seem it is not recognising the Sender as being a TComboBox.

If I try the same on the TButton section then we get the second attachment. F7 and this time it bounces into the code so it is recognising the Sender as being a TButton.

Eh? If I continue to run the program then it steps properly into the code that checks the ComboBoxes so it does recognise them for what they are. Perhaps there is some sort of 'Race' condition. When the frame is created The OnChange event is valid before the component has actually been created so things initially fall over.

As I mentioned at the start,

Quote
My, lack of, experience is that SIGSEGV occurs when you try to reference something that does not exist or does not exist yet..

Oh.... I do have similar code for a set of TEdits which works in the same way that TButtons does. Its just the TComboBox that is falling over. In part that is what confuses me.

Point taken about case with strings being slow. A long time ago I was using the tag element to make the choices and then I wondered if I could get things to work this way rather than poking about in the Object Inspector. I suppose I could avoid that or make things more apparent by explicitly coding it on initialisation.

In respect of my, lack of, naming convention, mumble, mumble mumble.
« Last Edit: February 21, 2016, 03:28:23 pm by MorbidFractal »

FTurtle

  • Sr. Member
  • ****
  • Posts: 292
Re: with Sender as [Thing] do
« Reply #14 on: February 21, 2016, 03:36:45 pm »
By the way, for reading about as and is:
http://www.freepascal.org/docs-html/ref/refsu52.html

 

TinyPortal © 2005-2018