Jump to content
David Schwartz

How to create a grid that looks like this

Recommended Posts

I'm curious how to create a grid of colored blobs that look like this, rather than your usual array of squared-off cells.

 

No gridlines, just colored blobs with some text in them. The fixed row and column are gray with text in them.

 

I'm not even sure how this one was created, but was asked if it's possible for my Delphi app to make something like this.

 

 

2021-08-07_15-59-22.png

Edited by David Schwartz

Share this post


Link to post

subclass (extend) Tshape with 
Tmyshape = class(Tshape)
  protected
    procedure Paint;
 public 
  Moniker: string;
end
...
{ TmyShape }
procedure TpatShape.Paint;
var
  w, h: integer;
  textSize: TSize;
begin
  inherited;
   
   Brush.Color := clBtnFace;
  with Canvas do
  begin
    font.Size := -15;
	textSize := TextExtent(Moniker);
	w := (Width - textSize.cx) div 2;
	h := (Height - textSize.cy) div 2;    
    TextOut(w,h,Moniker);
  end;

  //At runtime create custom shapes setting their parent to a floatPanel

 

Edited by Pat Foley
FlowPanel not floatPanel
  • Like 1

Share this post


Link to post

Should be easy to replicate that in a custom-drawn TDrawGrid/TStringGrid with its grid lines turned off, and an OnDrawCell event handler to draw the rounded blobs and text inside each cell.

Edited by Remy Lebeau
  • Like 6

Share this post


Link to post

I found an old component TjanRoundedButton on Torry's that I can put on a FlowPanel that gets me what I need.

Edited by David Schwartz
  • Like 1

Share this post


Link to post

I really like the TVirtualStringTree, but it will also end in custom drawing the cells.

 

Share this post


Link to post
54 minutes ago, David Schwartz said:

I found an old component TjanRoundedButton on Torry's that I can put on a FlowPanel that gets me what I need.

...one more dependency for this? I would go with remy's solution.

  • Like 1

Share this post


Link to post
14 hours ago, ConstantGardener said:

...one more dependency for this? I would go with remy's solution.

That's not "one more dependency" to me, it's "hundreds of lines of code I don't need to (re)write and maintain".

 

It's kinda like a homebuilder "buying lumber from a supplier [a dependency]" vs. "cutting down your own trees and making your own lumber".

 

The FlowPanel and GridPanel don't work very well, so I manually placed them on a regular panel. It gets me the visual layout that's needed.

Edited by David Schwartz

Share this post


Link to post

Hmm ok. For me is every dependency i can eleminate from my main project a win.

I try to focus on well maintained libs with sourcecode (TMS for example).

A not maintained component from torry would be an absolut no go for me. my 2 cent.

Share this post


Link to post

Well, I can get that, but it's the only thing I found that does what I'm looking for. And it was written for D3, D4, D5. It comes with source and isn't very complicated. And it compiled and ran with no issues. I'd have thought that somewhere in their vast array of stuff, TMS might have something, but I asked and Bruno said they don't. Raize has something that works under FMX, but this is a VCL app at the moment, and I'll be moving it to use TMS FNC components so I can webify it, so I may have to adapt it anyway. But for now it lets me keep moving forward.

Share this post


Link to post
Guest

I have personally avoided all "owner draw" thingies since HighDPI. It is detailed and cumbersome to write painting code, especially upon another component as the exact way it's done varies a lot. But that's me, i have always had a little "quiziness" for pixel handling. My 15 yrs old mastodont had a lot of owner draw. I took time to develop and it bites back sometimes. Enough tl;dr!

 

I have no idea about your budget, and did see "no more dependecies", but this seems like a "match in heaven" for https://www.delphihtmlcomponents.com/.

If you are using DevExpress it should be quite possible with their grid too, but the result IMHO would be a bit more efficient with htmlcomponents *if* using their "adorners" or similar.

 

HTH

Share this post


Link to post

I'm not buying an entire huge library for one simple UI feature. The TjanRoundedButton solves the problem from a visual standpoint, although it's not as easy to work with as I'd like.

 

(My Delphi license is up for renewal as well, and it ain't cheap either. That library is 2/3 the cost of my Delphi renewal. I only wish I could force everybody to give ME a mandatory 4% raise every year the way EMBT does with their maintenance deals.)

Edited by David Schwartz
  • Like 4

Share this post


Link to post

David

FNC has a "Tool Bar Button" which has some rounded corners. Might be worth a look.

  • Like 1

Share this post


Link to post

I found a component janShape V.4 here: http://sodev.webzdarma.cz/show.php?page=Panel&la=&kateg=Forms

 

It seems to be a newer version than jvShape that may be what's in the Jedi library.

 

I got it to install in D10.4.2 with minimal effort, but I can't get either version to do very much. 

 

You can drop an instance of it on a form and it's a small square white box that resembles a TShape. 

 

I set the Caption and it shows up as very light-green against white bg and is very hard to see.

 

Changing the Pen color does nothing.

 

Changing the Brush color does nothing.

 

Setting the Shape does nothing.

 

Almost every property that's changed issues an Invalidate call, so it should update what's displayed.

 

I do very little with the Canvas directly, so I'm not sure what I'm missing.

 

Is anybody familiar with this or how to get it to actually show something useful?

 

(Unfortunately, there's no sample included anywhere that I can find.)

Share this post


Link to post

I like the Tshape in VCL  It surfaces the pen and brush for setting in Object inspector properties. 

 

Here's some simple drawing techniques.

implementation

{$R *.dfm}
uses
  Vcl.Imaging.pngimage;
var
  png: TPngImage;
type
    TStarArray = array[0..10] of TPoint;

var
 StarPoints: TStarArray;

procedure drawStar(aImage: Timage; aPoint: TPoint; Ascale: single);
    begin
      var r: FixedInt := round(1 * ascale);
      var r12: FixedInt := round(0.45 * ascale);
      var tau: double := 2 * pi;
      for var I := Low(StarPoints) to High(StarPoints) do
        begin
          var rf: double;
          If odd(I) then rf:=r12 else rf := r;
          StarPoints[I].X := round(apoint.x + rf * SIN(tau * I/10));
          StarPoints[I].Y := round(apoint.Y + rf * -COS(tau * I/10));
        end;
      aImage.canvas.Brush.color := clred;
      aImage.canvas.polyGON(StarPoints);
    end;
procedure drawStarBM(aBM: TCanvas; aPoint: TPoint; Ascale: single);
    begin
      var r: FixedInt := round(1 * ascale);
      var r12: FixedInt := round(0.45 * ascale);
      var tau: double := 2 * pi;
      for var I := Low(StarPoints) to High(StarPoints) do
        begin
          var rf: double;
          If odd(I) then rf:=r12 else rf := r;
          //SineCosine()
          StarPoints[I].X := round(apoint.x + rf * SIN(tau * I/10));
          StarPoints[I].Y := round(apoint.Y + rf * -COS(tau * I/10));
        end;
      aBM.Brush.color := clred;
      aBM.polygon(StarPoints);
    end;

procedure TForm21.Button1Click(Sender: TObject);
begin
  with
  // self.
  // PaintBox.
    Image1. // finally persistent and could be passed as an argument if refactored
    canvas do
  begin
    var
    s := 'Stars';
    var
    Ycount := Height div 40; //
    var
    Xcount := Width div 80;
    var
      r: TRect;
    Brush.Color := clSilver;
    FillRect(ClientRect);

    for var Y := 0 to Ycount do
      for var X := 0 to Xcount do
      begin
        var
        Xa := 0 + round(X / Xcount * width);
        var
        Ya := 0 + round(Y / Ycount * Height);
        if  ((Xa=0) and (Ya=0)) then
          continue;

        if((Xa=0) or (Ya=0)) then
          Brush.Color := clSkyBlue
        else
          Brush.Color := clYellow;

        r.SetLocation(Xa, Ya);
        r.width := 145;
        r.Height := 80;
        roundrect(TRect(r), 18, 8);
        Textout(Xa + 6, Ya + 6, s);
        if not ((Xa=0) or (Ya=0)) and (random(10)>7) then
        DrawStar(Image1,point(Xa + 65, Ya + 15), 11);
      end;
     //Image1.Picture.SaveToFile('blobs.bmp');
     (*png := TPngImage.Create;
     png.Assign(Image1.Picture.Bitmap);
     png.SaveToFile('blobx.png');  *)

    // publish as html png later done
  end;
end;


// extended Tshape paint 
{ TSuperShape }

procedure TSuperShape.Paint;
var
  w, h: integer;
  textSize: TSize;
begin
  inherited;
  Brush.Color := clBtnFace;
  with Canvas do
  begin
    drawStarBM(Canvas,point(50,50),25);
    font.Size := -15;
	  textSize := TextExtent(Moniker);
	  w := (Width - textSize.cx) div 2;
	  h := (Height - textSize.cy) div 2;
    TextOut(w,h,Moniker);
  end;
end;

 

Edited by Pat Foley
add VCL

Share this post


Link to post

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

×