Jump to content


Photo

Listbox Items from custom class

Listbox TW3Listbox Class Item custom

  • Please log in to reply
5 replies to this topic

#1 ielite

ielite
  • Members
  • 723 posts

Posted 07 March 2017 - 03:59 AM

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.

 



#2 Nico Wouterse

Nico Wouterse
  • Moderators
  • 262 posts
  • LocationAustralia

Posted 07 March 2017 - 02:16 PM

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

 

Nico Wouterse

#3 ielite

ielite
  • Members
  • 723 posts

Posted 07 March 2017 - 11:04 PM

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



#4 Nico Wouterse

Nico Wouterse
  • Moderators
  • 262 posts
  • LocationAustralia

Posted 08 March 2017 - 04:20 AM

yep, you can do it in component form too

 

skeleton here


Nico Wouterse

#5 ielite

ielite
  • Members
  • 723 posts

Posted 20 March 2017 - 04:23 PM

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.


#6 ielite

ielite
  • Members
  • 723 posts

Posted 21 March 2017 - 02:05 AM

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;

  • Nico Wouterse likes this





Also tagged with one or more of these keywords: Listbox, TW3Listbox, Class, Item, custom

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users