Recent

Author Topic: [Solved] Question on CheckListBox  (Read 7555 times)

MathMan

  • Sr. Member
  • ****
  • Posts: 325
[Solved] Question on CheckListBox
« on: December 21, 2014, 01:43:34 pm »
Hi all,

I am currently using FPC 2.6.4., Lazarus 1.2.4 on Win 7/64.

In a benchmark unit I am using a CheckListBox for selection of functions to bench. So far I had it defined completely via object inspector - meaning when adding or deleting a function I had to change source code and make an equivalent change in the setup of the CheckListBox. As these things tend to screw up I wanted to initialize the items in the CheckListBox inside the benchmark unit. I found on message on the board regarding this and thought that something like the following would do

Code: [Select]
...

type

  { TBench }

  TBench = class(TForm)
    btnOK: TButton;
    btnCancel: TButton;
    clbFunc: TCheckListBox;
    gbFunc: TGroupBox;
    gbParam: TGroupBox;
    vleParams: TValueListEditor;
    procedure btnCancelClick(Sender: TObject);
    procedure btnOKClick(Sender: TObject);
    procedure btnOKEnter(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

...

type
  tTimeFunc = procedure();

  tBenchTab = record
    Func: tTimeFunc;
    Name: pChar;
    Dscr: pChar;
  end;

...

procedure lBenchInit();

var
  Count: Cardinal;

begin
  with Bench do
  begin
    for Count := 0 to SizeOf( BenchTab )-1 do
      clbFunc.Items.Add( BenchTab[ Count ].Dscr );
  end;
end;


Unfortunately all I get are runtime errors - I tried with an empty list in the object inspector, a list with one item, setting the item counter of the list to 0 before adding etc. etc.

Can anyone pls. help me with a link to a documentation how to work with CheckListBox or to a documented example in source pls.

Kind regards,
MathMan
« Last Edit: December 26, 2014, 12:09:14 am by MathMan »

Bart

  • Hero Member
  • *****
  • Posts: 5265
    • Bart en Mariska's Webstek
Re: Question on CheckListBox
« Reply #1 on: December 21, 2014, 01:47:30 pm »
Take a look at the PoChecker project (in componentns/pochecker/Proj) to see how you can do this by code.

Bart

MoellerCLaus

  • Full Member
  • ***
  • Posts: 114
    • Vig Foreningsprogram
Re: Question on CheckListBox
« Reply #2 on: December 21, 2014, 05:31:59 pm »
Checklistbox (also in Delphi) always leaves you with limited posibilities.

I have chosen consequently to use TStringgrid; here you can do everything :
  • Decent checkmarkes; own graphics if wanted
  • Different colors; lines
  • Editing possibilities
  • Etc.

and the best of it all -> Lazarus basic.


MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Question on CheckListBox
« Reply #3 on: December 21, 2014, 08:45:48 pm »
Take a look at the PoChecker project (in componentns/pochecker/Proj) to see how you can do this by code.

Bart

Hi Bart - thanks for hinting me there. I looked it up and found that the program encloses the CheckListBox in the main form

Code: [Select]
...

  TPoCheckerForm = class(TForm)
    ...
    OpenDialog: TOpenDialog;
    TestListBox: TCheckListBox;
    ...

So this is the same as my case. The CheckListBox gets initialized during FormCreate

Code: [Select]
procedure TPoCheckerForm.FormCreate(Sender: TObject);
...
begin
  ...
  FillTestListBox;
  ...
end;

I also do the initialization during FormCeate - so again this is equal. The "FillTestListBox" procedure then simply uses the Items.Add

Code: [Select]
procedure TPoCheckerForm.FillTestListBox;
var
  Opt: TPoTestOption;
begin
  for Opt := Low(PoTestOptionNames) to Pred(High(PoTestOptionNames)) do
    case Opt of
      ptoCheckNrOfItems: TestListBox.Items.Add(sCheckNumberOfItems);
      ptoCheckFormatArgs: TestListBox.Items.Add(sCheckForIncompatibleFormatArguments);
      ptoCheckMissingIdentifiers: TestListBox.Items.Add(sCheckMissingIdentifiers);
      ptoCheckMismatchedOriginals: TestListBox.Items.Add(sCheckForMismatchesInUntranslatedStrings);
      ptoCheckDuplicateOriginals: TestListBox.Items.Add(sCheckForDuplicateUntranslatedValues);
      ptoCheckStatistics: TestListBox.Items.Add(sCheckStatistics);
      else
        TestListBox.Items.Add(PoTestOptionNames[Opt]);
    end;
  SelectAllCheckBox.Caption := sSelectBasicTests;
end;

which also looks like what I am doing (see above - the size error for the count loop I have already removed). Also I found no hint of a Create etc. for TestListBox so I asume it was designed with the Object Inspector. In essence - all of the above looks exactly as my approach - but I am getting SIGSEGV???

Kind regards,
MathMan

Never

  • Sr. Member
  • ****
  • Posts: 409
  • OS:Win7 64bit / Lazarus 1.4
Re: Question on CheckListBox
« Reply #4 on: December 22, 2014, 12:27:17 am »
since you do not provide complete running code to reproduce the error is just guessing
assumming these are the only running lines and BenchTab is array of tBenchTab
Code: [Select]
  with Bench do
  begin
    for Count := 0 to SizeOf( BenchTab )-1 do
      clbFunc.Items.Add( BenchTab[ Count ].Dscr );
  end;
then your best bet is that
 you did not init the BenchTab array with values if the error is immediately after running the procedure
 or the count gets invalid values and overflows if the errors is with count>0
also if i understant correct you might need the length of the array and not the size of the array the size will return the size of the record the length will return the items  currently in the array
Edit**:just for the record
Code: [Select]
clbFunc.Items.Add( expects string
« Last Edit: December 22, 2014, 12:43:49 am by Never »
Νέπε Λάζαρε λάγγεψων οξωκά ο φίλοσ'ς αραεύσε

MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Question on CheckListBox
« Reply #5 on: December 22, 2014, 12:27:56 pm »
since you do not provide complete running code to reproduce the error is just guessing
assumming these are the only running lines and BenchTab is array of tBenchTab
Code: [Select]
  with Bench do
  begin
    for Count := 0 to SizeOf( BenchTab )-1 do
      clbFunc.Items.Add( BenchTab[ Count ].Dscr );
  end;
then your best bet is that
 you did not init the BenchTab array with values if the error is immediately after running the procedure
 or the count gets invalid values and overflows if the errors is with count>0
also if i understant correct you might need the length of the array and not the size of the array the size will return the size of the record the length will return the items  currently in the array
Edit**:just for the record
Code: [Select]
clbFunc.Items.Add( expects string

Hi Never,

BenchTab is initialized by the compiler as it is defined like

Code: [Select]
// ============================================================================
// Wrapper functions to allow calling from the benchmark function
// ============================================================================

procedure TimeStrip();
begin
  lStrip( Op1, Size1 );
end;
...
procedure TimeRor();
begin
  lRor( Op1, Op2, Size1 shl DSCALE, Size1 shl ( DSCALE-1 ) );
end;

// ============================================================================
// Table of timer functions, function name and description
// ============================================================================

const
  BenchTab: array [ 0..46 ] of tBenchTab =
    ( ( Func:@TimeStrip;     Name:'lStrip';     Dscr: 'Strip'                        ),
      ...
      ( Func:@TimeRor;       Name:'lRor';       Dscr: 'Rotate right by n'            ) );

Regarding the invalid count I spotted that one already and have changed the init procedure to

Code: [Select]
// ============================================================================
// Initialization of check list and parameter group box
// ============================================================================

procedure lBenchInit();

var
  Count: Integer;

begin
  // for every entry in BenchTab add the description to items in CheckListBox
  for Count := 0 to ( SizeOf( BenchTab ) div SizeOf( tBenchTab ) )-1 do
    Bench.clbFunc.Items.Add( BenchTab[ Count ].Dscr );
end;

Beside that I also did a dump to file to check if I am actually passing a string - and it checked ok. But maybe I am doing something wrong on the calling side as this is located in the FormCreate?

Code: [Select]
procedure TLongCalc.FormCreate(Sender: TObject);
begin
  lArithInit(); // initialize the arithmetic layer
  lBenchInit(); // initialize the benchmark unit
end;

Regards,
MathMan

Never

  • Sr. Member
  • ****
  • Posts: 409
  • OS:Win7 64bit / Lazarus 1.4
Re: Question on CheckListBox
« Reply #6 on: December 23, 2014, 12:02:10 am »
hello @MathMan

Code: [Select]
lenght(BenchTab )-1 is what you need to access all elements of the array
 a small project reproducing the error will help
Νέπε Λάζαρε λάγγεψων οξωκά ο φίλοσ'ς αραεύσε

MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Question on CheckListBox
« Reply #7 on: December 23, 2014, 12:14:36 am »
hello @MathMan

Code: [Select]
lenght(BenchTab )-1 is what you need to access all elements of the array
 a small project reproducing the error will help

Hi Never,

Pls. bear with me - I am working on it but I have to strip down substantially - hope to post something tomorrow ...

Kind regards,
MathMan

MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Question on CheckListBox
« Reply #8 on: December 23, 2014, 02:58:08 pm »
hello @MathMan

Code: [Select]
lenght(BenchTab )-1 is what you need to access all elements of the array
 a small project reproducing the error will help

Hi Never - pls. find attached. I stripped it down to the minimum without changing the execution flow. Probably I am doing something obvious wrong and will do the "head <=> desk" once solved  ;)

Regards,
MathMan

Never

  • Sr. Member
  • ****
  • Posts: 409
  • OS:Win7 64bit / Lazarus 1.4
Re: Question on CheckListBox
« Reply #9 on: December 23, 2014, 05:01:18 pm »
 from the top lazarus menu go  project/project options/-->
project options/forms/ click on forms
from the left panel (Auto created forms) use the arrows on the left and move the [ Bench] form to top this action will change the creation order of this form thus it will be created first
The sigsev produced because the code trying to access Bench and an object in Bench but
Bench is not created yet
« Last Edit: December 23, 2014, 05:57:41 pm by Never »
Νέπε Λάζαρε λάγγεψων οξωκά ο φίλοσ'ς αραεύσε

MathMan

  • Sr. Member
  • ****
  • Posts: 325
Re: Question on CheckListBox
« Reply #10 on: December 23, 2014, 06:11:35 pm »
from the top lazarus menu go  project/project options/-->
project options/forms/ click on forms
from the left panel (Auto created forms) use the arrows on the left and move the [ Bench] form to top this action will change the creation order of this form thus it will be created first
The sigsev produced because the code trying to access Bench and an object in Bench but
Bench is not created yet

Thanks! Just tested and it works. From a more general perspective the way I approached it is not a good one if it is depending on the sequence of form creations. Is there a better way to do this - e.g. an event related to tApplication that is allways called but after all forms have been created? One alternative seems to be to relocate the call to lBenchInit into a Bench.FormCreate - but if possible I would rather have all calls to init procedures at a central place of the application.

Never

  • Sr. Member
  • ****
  • Posts: 409
  • OS:Win7 64bit / Lazarus 1.4
Re: Question on CheckListBox
« Reply #11 on: December 24, 2014, 01:03:51 pm »
Quote
From a more general perspective the way I approached it is not a good one if it is depending on the sequence of form creations
the confusion occures because you are mixing data with user views
if you need the array and other staff inside the Bench, in several places then create a separate unit to hold them and share this unit when there is a need
then it will be clear that the best place to load the checklist is the  Bench.FormCreate
Νέπε Λάζαρε λάγγεψων οξωκά ο φίλοσ'ς αραεύσε

 

TinyPortal © 2005-2018