Which Control/Component Can Load Images In Cells lazarus / 39-Graphics ---------------------------------------------------------------------- AaronCatolico1 · 2024-10-30 03:34 I'm new to using Lazarus. I'm trying to figure out which component/control is capable of loading image icons, progressbars, buttons, etc., inside of the cells. For example, a control such as TListView or TDBGrid, etc.. Which one is capable of loading images in any random column or row when needed? I'm looking for something that can do what Delphi is doing in their grids and listviews. Can Lazarus do this as well? If so, which control should I use to load small image icons? ---------------------------------------------------------------------- cdbc · 2024-10-30 04:15 Hi I'd say, off the bat, 'TListView' will do that, but there are others, that can be made to do it as well... Regards Benny ---------------------------------------------------------------------- AaronCatolico1 · 2024-10-30 04:45 Yeah, I'm looking for something like this: ---------------------------------------------------------------------- Handoko · 2024-10-30 06:26 I don't think there is any ready-made component that has those features. But Lazarus is very powerful, I don't see any problem to get the result you want. For example, I 'improved' TScrollBox to store texts with features: - Add, delete, remove, rename - Icons that appear when mouse pointer is hovering on the line - Checkbox to allow multiple selections - Customizable popup ---------------------------------------------------------------------- Thaddy · 2024-10-30 07:52 TDrawGrid.... ---------------------------------------------------------------------- paweld · 2024-10-30 08:35 Check out KGrid/KDBGrid from the KControls component package: https://wiki.freepascal.org/KControls You can also use VirtualStringTree - it's in the standard lazarus installation under the name LazVirtualStringTree. ---------------------------------------------------------------------- marcov · 2024-10-30 09:04 I had the same problem long ago (and before Delphi had those components), and used virtual string tree/grid on Delphi. I happened to try to port that to Lazarus a good month ago, and I noticed that the tcheckbox behaviour of Lazarus is different than Delphi and put it on ice for now. (e.g. lazarus has an onchange and Delphi not). Now I know that back then I had trouble getting Delphi to work too, so this is not 100% Lazarus fault,  it is a convoluted and sensitive problem with multiple levels of event (grid+ components) ---------------------------------------------------------------------- AaronCatolico1 · 2024-10-30 14:21 This looks like a very nice little example. So, what's the concept behind achieving this? Thanks. Quote from: Handoko on October 30, 2024, 07:26:34 amI don't think there is any ready-made component that has those features. But Lazarus is very powerful, I don't see any problem to get the result you want. For example, I 'improved' TScrollBox to store texts with features: - Add, delete, remove, rename - Icons that appear when mouse pointer is hovering on the line - Checkbox to allow multiple selections - Customizable popup ---------------------------------------------------------------------- Handoko · 2024-10-30 16:25 OOP is the key in this case. I'm not saying Object Oriented Programming is the 'wonder drug' for solving many problems in programming. Actually, I now try to reduce my OOP usage and use more the traditional procedural approach. OOP is a double-edge sword, I started to see the disadvantages of using OOP. But OOP can be a very good solution in programming if you use it wisely. And Lazarus/Pascal has good support for OOP approach. Actually I am not a programmer, I am a freelance web/graphics designer. All my work results need to be looking good. When I write programs, I want the user interface to looks good too. Lazarus has plenty of visual components, but I often need to customize them to get the visual result I want. Most or maybe all of Lazarus' visual components are written using OOP approach. So if you are good in OOP, it will be easy for you to 'extend' the components to reach the result you need. That is not hard. But you really need to have the knowledge about it. I found out that most of Lazarus' components are well written that allow you to improve, subclass, customize its appearance easily. Not happy with their default appearances,  I 'played' and added a lot of visual features in TOpenGLControl, TStringGrid, TPageControl, TForm, TBitmap, etc. The screenshot/video I showed you, actually is a component that consists of 3 classes: - TIBToolBar - TIBItem   <--- this is the main component, subclassed from TScrollBox - TIBItemBox The whole source code has 1110 lines of code. If you curious, here I can show the declaration part of the classes: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type   TIBToolBar     = class;  TIBItem        = class;  TIBItemBox     = class;  TIBToolClicked = (itNone, itCheckBox, itArrowUp, itArrowDown);   { TIBToolItem }   TIBToolItem = class  private    FCanvas:  TCanvas;    FChecked: Boolean;    FIndex:   Integer;    FToolBar: TIBToolBar;    FVisible: Boolean;    function ClickNormal(const aParent: TScrollBox): TIBToolClicked; virtual;    procedure ClickShift(const aParent: TScrollBox); virtual;    procedure DoDraw(const aBackgroundColor: TColor; const X: Integer); virtual;    procedure LineRel(const X, Y: LongInt);  public    constructor Create; virtual;    procedure DrawToolItem(const aBackgroundColor: TColor; const X: Integer);    function Width: Integer; virtual;  end;   { TIBToolCheckBox }   TIBToolCheckBox = class(TIBToolItem)  private    function ClickNormal(const aParent: TScrollBox): TIBToolClicked; override;    procedure ClickShift(const aParent: TScrollBox); override;    procedure DoDraw(const aBackgroundColor: TColor; const X: Integer); override;  public    function Width: Integer; override;  end;   { TIBToolArrowUp }   TIBToolArrowUp = class(TIBToolItem)  private    function ClickNormal(const aParent: TScrollBox): TIBToolClicked; override;    procedure DoDraw(const aBackgroundColor: TColor; const X: Integer); override;  public    constructor Create; override;    function Width: Integer; override;  end;   { TIBToolArrowDown }   TIBToolArrowDown = class(TIBToolItem)  private  function ClickNormal(const aParent: TScrollBox): TIBToolClicked; override;    procedure DoDraw(const aBackgroundColor: TColor; const X: Integer); override;  public    constructor Create; override;    function Width: Integer; override;  end;   { TIBToolBar }   TIBToolBar = class(TFPObjectList)  private    FParent: TIBItem;    FPosX:   Integer;  public    constructor Create(const aParent: TIBItem; const X: Integer); overload;    procedure Add(const aToolItem: TIBToolItem);    procedure DrawToolBar(const aBackgroundColor: TColor; const MouseX: Integer);    procedure ShowTool(const anIndex: Integer; const aStatus: Boolean);  end;   { TIBItem }   TIBItem = class(TScrollBox)  const    FLeft = 70;  private    FColorHighLighted:   TColor;    FColorNormal:        TColor;    FContent:            shortstring unimplemented;    FDoubleClickTesting: Boolean;    FLastClick:          TDateTime;    FList:               TIBItemBox; // Parent's list    FToolBar:            TIBToolBar;    procedure DrawContent; virtual;    function IsMouseHovering: Boolean;    function IsMouseHoverToolItem(const anIndex, MouseX: Integer): Boolean;    function ItemHeight: Integer; virtual;    procedure EventAddClick(Sender: TObject);    procedure EventClick(Sender: TObject);    procedure EventDeleteClick(Sender: TObject);    procedure EventDblClick(Sender: TObject);    procedure EventEditClick(Sender: TObject);    procedure EventMouseEnter(Sender: TObject);    procedure EventMouseLeave(Sender: TObject);    procedure EventMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);  public    constructor Create; overload;    constructor Create(aOwner: TComponent; const S: string = '');    procedure Paint; override;    property Data: shortstring read FContent write FContent;  end;   { TIBItemEmpty }   TIBItemEmpty = class(TIBItem) // Used to pass @TIBItemBox to ItemBoxOf  public    constructor Create(aOwner: TComponent); override;  end;   { TIBItemBox }   TIBItemBoxEventEnum = (ieToolUp, ieToolDown, ieEdit, ieInsert,    ieAdd, ieDelete, ieDisconnect);  TIBItemBoxEvent = procedure(ItemBox: TIBItemBox; Index1, Index2: Integer;    Event: TIBItemBoxEventEnum) of object;   TIBItemBox = class(TFPObjectList)  private    FHovering:        Integer;    FEvent:           TIBItemBoxEvent;    FMenuCaption:     array[1..10] of string;    FMenuEvent:       array[1..10] of TNotifyEvent;    FMenuCount:       Integer;    FScrollBox:       TScrollBox;    FTimerDelete:     TTimer; // Prevent deleting while manipulating item    FTimerDisconnect: TTimer;    procedure EventAddClick(Sender: TObject);    procedure EventMouseDown(Sender: TObject; Button: TMouseButton;      Shift: TShiftState; X, Y: Integer);    procedure EventResize(Sender: TObject);    procedure EventTimerDelete(Sender: TObject);    procedure EventTimerDisconnect(Sender: TObject);  public    constructor Create(const aScrollBox: TScrollBox);    procedure Add(const anItem: TIBItem);    procedure CheckedAdd;    procedure CheckedDelete;    function CheckedFirst: Integer;    function CheckedLast: Integer;    function Disconnect: Boolean;    function Hovering: Integer;    function isEmpty: Boolean;    procedure Migrate(const aSource: TIBItemBox; const anIndexFrom, anIndexTo: Integer);    function GetScrollBox: TScrollBox;    procedure Rename(const S: string);    procedure SetEventResponse(const anEvent: TIBItemBoxEvent);    procedure SetMenu(const aCaption: string; const anEvent: TNotifyEvent);  end; When I managed to make TItemBox to work correctly, I was very happy about it. It now could have addable and customizable icons, color highlight when mouse hovering, and many cool features I wanted. But I abandoned the code. As I said, OOP has its own disadvantages. When the code grows bigger to a certain point, it will become too hard to maintain if you didn't plan it properly at the very beginning. You are new in Lazarus. I understand you have doubt about what can be done using Lazarus. I can sure to tell you, Lazarus is very powerful. Most of the components can be easily subclassed and improved if you know how to do it. And the Pascal language itself, is not perfect, but very good. ---------------------------------------------------------------------- wp · 2024-10-30 19:26 Quote from: AaronCatolico1 on October 30, 2024, 04:34:02 amI'm looking for something that can do what Delphi is doing in their grids and listviews. Can Lazarus do this as well? If so, which control should I use to load small image icons? This reads as if you are looking for a "super grid" which contains "all" features you can think of... Is that really necessary? The higher your requirements the smaller the chance that you will find a working existing solution somewhere, and vice versa. For example, when the grid in your "dbgrid2.jpg" screenshot, is enough then you can do everything in the TDrawGrid which comes with Lazarus - no special component needed. You'll have to do some programming, though... See attachment ---------------------------------------------------------------------- Thaddy · 2024-10-30 19:34 WTF is wrong with TDrawGrid? Is somebody looking for a more complex way? ---------------------------------------------------------------------- AaronCatolico1 · 2024-10-30 20:01 Wow! Thank you for your efforts! I will definitely consider using this language and these frameworks. Also, what about in terms of cross-platform compatibility? How hard would it be to get a tool you built, or say, a TDrawGrid to become cross-compatible with an Android, iOS, MAC, Linux, etc.? Is it truly a "code once, deploy anywhere" or do you have to jump through multiple hoops difficult to fit through? Thanks again! Quote from: Handoko on October 30, 2024, 05:25:14 pmOOP is the key in this case. I'm not saying Object Oriented Programming is the 'wonder drug' for solving many problems in programming. Actually, I now try to reduce my OOP usage and use more the traditional procedural approach. OOP is a double-edge sword, I started to see the disadvantages of using OOP. But OOP can be a very good solution in programming if you use it wisely. And Lazarus/Pascal has good support for OOP approach. Actually I am not a programmer, I am a freelance web/graphics designer. All my work results need to be looking good. When I write programs, I want the user interface to looks good too. Lazarus has plenty of visual components, but I often need to customize them to get the visual result I want. Most or maybe all of Lazarus' visual components are written using OOP approach. So if you are good in OOP, it will be easy for you to 'extend' the components to reach the result you need. That is not hard. But you really need to have the knowledge about it. I found out that most of Lazarus' components are well written that allow you to improve, subclass, customize its appearance easily. Not happy with their default appearances,  I 'played' and added a lot of visual features in TOpenGLControl, TStringGrid, TPageControl, TForm, TBitmap, etc. The screenshot/video I showed you, actually is a component that consists of 3 classes: - TIBToolBar - TIBItem   <--- this is the main component, subclassed from TScrollBox - TIBItemBox The whole source code has 1110 lines of code. If you curious, here I can show the declaration part of the classes: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type   TIBToolBar     = class;  TIBItem        = class;  TIBItemBox     = class;  TIBToolClicked = (itNone, itCheckBox, itArrowUp, itArrowDown);   { TIBToolItem }   TIBToolItem = class  private    FCanvas:  TCanvas;    FChecked: Boolean;    FIndex:   Integer;    FToolBar: TIBToolBar;    FVisible: Boolean;    function ClickNormal(const aParent: TScrollBox): TIBToolClicked; virtual;    procedure ClickShift(const aParent: TScrollBox); virtual;    procedure DoDraw(const aBackgroundColor: TColor; const X: Integer); virtual;    procedure LineRel(const X, Y: LongInt);  public    constructor Create; virtual;    procedure DrawToolItem(const aBackgroundColor: TColor; const X: Integer);    function Width: Integer; virtual;  end;   { TIBToolCheckBox }   TIBToolCheckBox = class(TIBToolItem)  private    function ClickNormal(const aParent: TScrollBox): TIBToolClicked; override;    procedure ClickShift(const aParent: TScrollBox); override;    procedure DoDraw(const aBackgroundColor: TColor; const X: Integer); override;  public    function Width: Integer; override;  end;   { TIBToolArrowUp }   TIBToolArrowUp = class(TIBToolItem)  private    function ClickNormal(const aParent: TScrollBox): TIBToolClicked; override;    procedure DoDraw(const aBackgroundColor: TColor; const X: Integer); override;  public    constructor Create; override;    function Width: Integer; override;  end;   { TIBToolArrowDown }   TIBToolArrowDown = class(TIBToolItem)  private  function ClickNormal(const aParent: TScrollBox): TIBToolClicked; override;    procedure DoDraw(const aBackgroundColor: TColor; const X: Integer); override;  public    constructor Create; override;    function Width: Integer; override;  end;   { TIBToolBar }   TIBToolBar = class(TFPObjectList)  private    FParent: TIBItem;    FPosX:   Integer;  public    constructor Create(const aParent: TIBItem; const X: Integer); overload;    procedure Add(const aToolItem: TIBToolItem);    procedure DrawToolBar(const aBackgroundColor: TColor; const MouseX: Integer);    procedure ShowTool(const anIndex: Integer; const aStatus: Boolean);  end;   { TIBItem }   TIBItem = class(TScrollBox)  const    FLeft = 70;  private    FColorHighLighted:   TColor;    FColorNormal:        TColor;    FContent:            shortstring unimplemented;    FDoubleClickTesting: Boolean;    FLastClick:          TDateTime;    FList:               TIBItemBox; // Parent's list    FToolBar:            TIBToolBar;    procedure DrawContent; virtual;    function IsMouseHovering: Boolean;    function IsMouseHoverToolItem(const anIndex, MouseX: Integer): Boolean;    function ItemHeight: Integer; virtual;    procedure EventAddClick(Sender: TObject);    procedure EventClick(Sender: TObject);    procedure EventDeleteClick(Sender: TObject);    procedure EventDblClick(Sender: TObject);    procedure EventEditClick(Sender: TObject);    procedure EventMouseEnter(Sender: TObject);    procedure EventMouseLeave(Sender: TObject);    procedure EventMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);  public    constructor Create; overload;    constructor Create(aOwner: TComponent; const S: string = '');    procedure Paint; override;    property Data: shortstring read FContent write FContent;  end;   { TIBItemEmpty }   TIBItemEmpty = class(TIBItem) // Used to pass @TIBItemBox to ItemBoxOf  public    constructor Create(aOwner: TComponent); override;  end;   { TIBItemBox }   TIBItemBoxEventEnum = (ieToolUp, ieToolDown, ieEdit, ieInsert,    ieAdd, ieDelete, ieDisconnect);  TIBItemBoxEvent = procedure(ItemBox: TIBItemBox; Index1, Index2: Integer;    Event: TIBItemBoxEventEnum) of object;   TIBItemBox = class(TFPObjectList)  private    FHovering:        Integer;    FEvent:           TIBItemBoxEvent;    FMenuCaption:     array[1..10] of string;    FMenuEvent:       array[1..10] of TNotifyEvent;    FMenuCount:       Integer;    FScrollBox:       TScrollBox;    FTimerDelete:     TTimer; // Prevent deleting while manipulating item    FTimerDisconnect: TTimer;    procedure EventAddClick(Sender: TObject);    procedure EventMouseDown(Sender: TObject; Button: TMouseButton;      Shift: TShiftState; X, Y: Integer);    procedure EventResize(Sender: TObject);    procedure EventTimerDelete(Sender: TObject);    procedure EventTimerDisconnect(Sender: TObject);  public    constructor Create(const aScrollBox: TScrollBox);    procedure Add(const anItem: TIBItem);    procedure CheckedAdd;    procedure CheckedDelete;    function CheckedFirst: Integer;    function CheckedLast: Integer;    function Disconnect: Boolean;    function Hovering: Integer;    function isEmpty: Boolean;    procedure Migrate(const aSource: TIBItemBox; const anIndexFrom, anIndexTo: Integer);    function GetScrollBox: TScrollBox;    procedure Rename(const S: string);    procedure SetEventResponse(const anEvent: TIBItemBoxEvent);    procedure SetMenu(const aCaption: string; const anEvent: TNotifyEvent);  end; When I managed to make TItemBox to work correctly, I was very happy about it. It now could have addable and customizable icons, color highlight when mouse hovering, and many cool features I wanted. But I abandoned the code. As I said, OOP has its own disadvantages. When the code grows bigger to a certain point, it will become too hard to maintain if you didn't plan it properly at the very beginning. You are new in Lazarus. I understand you have doubt about what can be done using Lazarus. I can sure to tell you, Lazarus is very powerful. Most of the components can be easily subclassed and improved if you know how to do it. And the Pascal language itself, is not perfect, but very good. ---------------------------------------------------------------------- AaronCatolico1 · 2024-10-30 20:58 Wow! That looks really nice! Very impressive! I appreciate this. This looks like something im interested in. Please provide me with the sourcecode so i can study over it. Thanks again. Quote from: wp on October 30, 2024, 08:26:55 pmQuote from: AaronCatolico1 on October 30, 2024, 04:34:02 amI'm looking for something that can do what Delphi is doing in their grids and listviews. Can Lazarus do this as well? If so, which control should I use to load small image icons? This reads as if you are looking for a "super grid" which contains "all" features you can think of... Is that really necessary? The higher your requirements the smaller the chance that you will find a working existing solution somewhere, and vice versa. For example, when the grid in your "dbgrid2.jpg" screenshot, is enough then you can do everything in the TDrawGrid which comes with Lazarus - no special component needed. You'll have to do some programming, though... See attachment ---------------------------------------------------------------------- wp · 2024-10-30 22:56 Quote from: AaronCatolico1 on October 30, 2024, 09:58:22 pmPlease provide me with the sourcecode so i can study over it. Thanks again. The source code (including lots of comments) is in the attachment of my post. ---------------------------------------------------------------------- AaronCatolico1 · 2024-10-31 04:10 I didn't realize that you had it attached. I believe originally it was only showing the image. So, where is the official documentation of how to populate this TDrawGrid or where did you learn it from? I'd like to review this documentation.