Jump to content
IElite

Listbox Items from custom class

Recommended Posts

I am trying to create a listbox that has an Image and Label on each item. The image is aligned left, and the label is aligned client.

 

Why doesn't the code below work?  I never get anything on the ListBox items (no images or labels)

 

unit Main;

interface

uses 
  SmartCL.System, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms, 
  SmartCL.Fonts, SmartCL.Borders, SmartCL.Application, SmartCL.Layout,
  SmartCL.Controls.Listbox, System.Colors;

type
  TfrmMain = class(TW3Form)
  private
    {$I 'Main:intf'}
    fLayout: TLayout;
    procedure AddItem(Caption: String; Image: String);
  protected
    procedure InitializeForm; override;
    procedure InitializeObject; override;
    procedure Resize; override;
  end;

implementation

uses LBItem;

{ TForm1 }

 procedure TfrmMain.AddItem(Caption: String; Image: String);
 begin
   var lbItem := W3ListBox.Items[W3ListBox.Add] as TLBItem;
   lbItem.Caption:= Caption;
   lbItem.Image:= Image;
 end;

procedure TfrmMain.InitializeForm;
begin
  inherited;
  // this is a good place to initialize components
   FLayout:= Layout.Client(W3ListBox);
end;

procedure TfrmMain.InitializeObject;
begin
  inherited;
  {$I 'Main:impl'}
  
  W3ListBox.ItemClass := TLBItem;
  W3ListBox.ItemHeight := 32;
  W3ListBox.Styles.SelectedColor := clSilver;

  AddItem('One', 'res\1.png');
  AddItem('Two', 'res\2.png');
  AddItem('Three', 'res\3.png');
  AddItem('Four', 'res\4.png');
  AddItem('Five', 'res\5.png');

end;

procedure TfrmMain.Resize;
begin
  inherited;
  if Assigned(FLayout) then
  begin
    FLayout.Resize(self);
  end;
end;

initialization
  Forms.RegisterForm({$I %FILE%}, TfrmMain);
end.
unit LBItem;

interface

uses 
  System.Types, SmartCL.System, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms,
  SmartCL.Fonts, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Header,
  SmartCL.Controls.CheckBox, SmartCL.Controls.Image, SmartCL.Layout,
  SmartCL.Controls.Label;

type
  TLBItem = class(TW3Form)
  private
    {$I 'LBItem:intf'}
    fLayout: TLayout;
    procedure SetImage(Value: String);
    function GetImage: String;
    procedure SetCaption(Value: String);
    function GetCaption: String;
  protected
    procedure InitializeForm; override;
    procedure InitializeObject; override;
    procedure Resize; override;
  public
   property Image: String read GetImage write SetImage;
   property Caption: String read GetCaption write SetCaption;
  end;

implementation

{ TLBItem }

procedure TLBItem.SetCaption(Value: String);
begin
 W3Label.Caption:= Value;
end;

function TLBItem.GetCaption: String;
begin
 result:= W3Label.Caption;
end;

procedure TLBItem.SetImage(Value: String);
begin
 W3Image.LoadFromUrl(Value);
end;

function TLBItem.GetImage: String;
begin
 result:= W3Image.Url;
end;

procedure TLBItem.InitializeForm;
begin
  inherited;
  // this is a good place to initialize components
  Layout.Client([Layout.Left(W3Image),
                Layout.Left(W3Label)]);
end;

procedure TLBItem.InitializeObject;
begin
  inherited;
  {$I 'LBItem:impl'}
   W3Image.Width:= 32;
   W3Image.Height:= 32;
  
   W3Label.Height:= 32;
   W3Label.Width:= 32;
end;

procedure TLBItem.Resize;
begin
  inherited;
   if Assigned(FLayout) then
  begin
    FLayout.Resize(self);
  end;
end;

initialization
  Forms.RegisterForm({$I %FILE%}, TLBItem);
end.

 

Share this post


Link to post
Share on other sites

I see you derive your items from TW3Form, is that what you want ?

and if so, do you create them somewhere ?

 

A slightly different approach :

1) create a listbox

2) for every item to add, add a panel to 1) and adjust height

3) for every panel 2), add a label and an image to it

 

or in pseudo code 

 
  TForm1 :
    ListBox1: TW3Panel;
    ListBoxH : Integer;
    procedure AddItem(label: string; image: string);
 
init:
  ListBox1 := TW3Panel.Create(Self);
  ListBoxH := 0;
  AddItem('One', 'res\1.png');
  AddItem('Two', 'res\2.png');
...
 
Procedure AddItem (label,  image);
  var item := TW3Panel.Create(ListBox1);
  item.top := ListBoxH;
  item.Height := 99;
  ListBoxH := ListBoxH + item.Height;
 
  var edit := TW3Label.Create(item);
  edit.setbounds(left, top, width, trunc(item.ClientHeight/2);
  Edit.Caption := label;
 
//same with image

 

Share this post


Link to post
Share on other sites

Shouldn't we be able to create the ListBox item class, all within the class declaration.  i.e. the Image and label 

 

and not have to do it on the Main Form (list Box) side?

 

 

All i want is a ListBox item class that has a Image aligned left and a Label aligned client

Share this post


Link to post
Share on other sites

OK, i have made some chnges to my TLIstBoxItem class  (mainly deriving it from TW3CustomControl instead of TW3form) - but some other changes to the private members and public properties as well

 

The project is listed here on github

 

but here is the class and my main unit as well

 

like i said, everything seeems to work as I expected, except the text doesn't display for each of the listbox items - only the image

unit ListBoxItem;


interface


uses 
 SmartCL.Components, SmartCL.Controls.Label, SmartCL.Controls.Image,
 SmartCL.Layout, System.Colors;


type
  TListBoxItem = class(TW3CustomControl)
  private
    fLayout: TLayout;
    fLabel: TW3Label;
    fImage: TW3Image;
  protected
    procedure InitializeObject; override;
    procedure Resize; override;
  public
   property Text: string read (fLabel.Caption) write (fLabel.Caption);
   property Url: String read  (fImage.Url) write (fImage.Url);
  end;


  function window: variant; external 'window' property;


implementation


{ TListBoxItem }




procedure TListBoxItem.InitializeObject;
begin
  inherited;
   window.addEventListener('devicemotion', @Resize, false);
  fImage:= TW3Image.create(self);
  fLabel:= TW3Label.create(self);
  fLabel.Color:= clRed;
  fLabel.AlignText:= taCenter;
  fImage.Width:= 32;
  fLabel.Width:= 32;
  fLabel.Font.Color:= clYellow;
  Layout.Client(Layout.Padding(3),[layout.Left(fImage), Layout.Client(fLabel)]);
end;


procedure TListBoxItem.Resize;
begin
  inherited;
  if Assigned(FLayout) then
  begin
    fLayout.Resize(Self);
  end;
end;


end.

unit Main;


interface


uses 
  SmartCL.System, SmartCL.Graphics, SmartCL.Components, SmartCL.Forms, 
  SmartCL.Fonts, SmartCL.Borders, SmartCL.Application, SmartCL.Layout,
  SmartCL.Controls.Listbox, SmartCL.Inet, ECMA.JSON, System.Colors;


type
  TMain = class(TW3Form)
  private
    {$I 'Main:intf'}
    fLayout: TLayout;
    fHttp: TW3HttpRequest;
    fJSONStr: String;
    fChallenges: Variant;
    procedure AddItem(Caption: String);
  protected
    procedure HandleHttpDataReady(Sender:TW3HttpRequest);
    procedure InitializeForm; override;
    procedure InitializeObject; override;
    procedure Resize; override;
  end;


  function window: variant; external 'window' property;


implementation


uses ListBoxItem;


{ TForm1 }


procedure TMain.AddItem(Caption: String);
 begin
   var lbItem := lbxChallenges.Items[lbxChallenges.Add] as TListBoxItem;
   lbItem.Text:= Caption;
   lbItem.Url:= 'res\mtn.png';
 end;




procedure TMain.HandleHttpDataReady(Sender:TW3HttpRequest);
begin
  fJSONStr:= Sender.ResponseText;
  asm
   @fChallenges = JSON.parse(@fJSONStr);
  end;
end;


procedure TMain.InitializeForm;
begin
  inherited;
  // this is a good place to initialize components
  fHttp.Get('res\challenges.json');
end;


procedure TMain.InitializeObject;
var
 I: integer;
begin
  inherited;
  {$I 'Main:impl'}
   window.addEventListener('devicemotion', @Resize, false);
   FLayout:= Layout.Client(Layout.Client(lbxChallenges));
   fHttp := TW3HttpRequest.Create;
   fHttp.OnDataReady:= HandleHttpDataReady;


  lbxChallenges.ItemClass := TListBoxItem;
  lbxChallenges.ItemHeight := 32;
  lbxChallenges.Styles.SelectedColor := clSilver;


  AddItem('One');
  AddItem('Two');
  AddItem('Three');
end;


procedure TMain.Resize;
begin
  inherited;
   if Assigned(FLayout) then
  begin
    FLayout.Resize(self);
  end;
end;


initialization
  Forms.RegisterForm({$I %FILE%}, TMain);
end.

Share this post


Link to post
Share on other sites

looks like this bit of code works

 

 

procedure TListBoxItem.InitializeObject;
begin
  inherited;
  fImage:= TW3Image.create(self);
  fImage.Width:= 32;
  fLabel:= TW3Label.create(self);
  fLabel.AlignText:= taCenter;


  FLayout:= Layout.Client([
                           Layout.Left(Layout.Width(32), fImage),
                           Layout.Client(fLabel)
                          ]);




end;

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×