Recent

Author Topic: How best to set this up - suggestions welcome!  (Read 2004 times)

rwebb616

  • Full Member
  • ***
  • Posts: 133
How best to set this up - suggestions welcome!
« on: April 06, 2021, 09:56:16 pm »
Hello All!

I am designing an application that has what we will call a Gameboard.  This gameboard will be used to display various things throughout it's lifecycle.  Here are some of the items:
  • A Title screen that has a label centered near the top
  • A Word label that will be centered in the exact center
  • Up to 6 category labels that will be dynamically generated and placed in 2 columns and 3 rows
  • On the same category screen two lines of centered labels near the top

My question really is more about the easiest way to generate and position the labels.  I was thinking about creating some functions that return the top/left coordinates of the controls and maybe passing it a reference to the control. 

Thought about having named positions maybe using an enum maybe or something similar .. anyway if anyone needs more clarification on this please ask.

Thanks!
Rich

Handoko

  • Hero Member
  • *****
  • Posts: 5158
  • My goal: build my own game engine using Lazarus
Re: How best to set this up - suggestions welcome!
« Reply #1 on: April 06, 2021, 10:05:24 pm »
I saw you post it on the Free Pascal sub forum. Have you consider to use Lazarus. It will be easiest doing it using Lazarus. To centering a text:

1. Drop a TLabel to the form
2. Set TLabel.AutoSize to False
3. Set TLabel.Alignment to taCenter

But if you prefer to do it on console/text mode, you have you write a function/procedure for doing the text positioning and alignment.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: How best to set this up - suggestions welcome!
« Reply #2 on: April 06, 2021, 10:08:45 pm »
If you use Lazarus you could place your 6 category labels on a borderless panel and use its ChildSizing properties to get them automatically positioned correctly.

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: How best to set this up - suggestions welcome!
« Reply #3 on: April 06, 2021, 10:09:40 pm »
Yes, I'm designing this in Lazarus.  I'm generating the labels dynamically through code

The categories are starting out in a checklistbox where the user checks up to 6 categories. Then this procedure runs when "show categories" is clicked.

Code: Pascal  [Select][+][-]
  1. procedure TfMainForm.ShowCategories;
  2. type
  3.   CatArray = array  [1..2,1..3] of string;
  4. var
  5.   categories : Tstringlist;
  6.   struct : CatArray;
  7.   i : integer;
  8.   x,y : integer;
  9. begin
  10.   categories := Tstringlist.create;
  11.   for i:=0 to clbCategories.Count - 1 do begin
  12.     if clbCategories.Checked[i] then
  13.       categories.Add(clbCategories.items[i]);
  14.   end;
  15.   //showmessage(categories.Count.ToString);
  16.   i:=0;
  17.     for y := 1 to 3 do begin
  18.       for x := 1 to 2 do
  19.         if i < categories.Count then begin
  20.           struct[x,y] := categories[i];
  21.           inc(i);
  22.         end
  23.         else
  24.           inc(i);
  25.     end;
  26.  
  27.     fGameboard.ShowCategories(struct);
  28.     categories.Free;
  29. end;

Then on the gameboard it's taking the array and creating/printing the labels to the form in 2 columns and 3 rows.:

Code: Pascal  [Select][+][-]
  1. procedure TfGameboard.ShowCategories(Categories: CatArray);
  2. var
  3.   i,x,y : integer;
  4.   rows : array [1..3] of integer;
  5.   cols : array [1..2] of integer;
  6.   labels : array of Tlabel;
  7. begin
  8.   // Hide title label;
  9.   self.lblTitle.Hide;
  10.  
  11.   // Show list of categories
  12.   // Get centers of rows and columns
  13.   Rows[1] := (self.Height div 2) div 2;
  14.   Rows[2] := (self.height div 2);
  15.   Rows[3] := (self.Height div 2) + Rows[1];
  16.   cols[1] := (self.Width div 2) div 2;
  17.   cols[2] := (self.Width div 2) + cols[1];
  18.  
  19.   // Set categories background
  20.   setimage(imgBackground.Picture,'CATEGORIES');
  21.  
  22.   // create labels and set their contents
  23.   i:=0;
  24.   for y := 1 to 3 do begin
  25.     for x := 1 to 2 do begin
  26.       if categories[x,y] <> '' then begin
  27.           setlength(labels,i+1);
  28.           labels[i]:=Tlabel.Create(self);
  29.           labels[i].Caption:=categories[x,y];
  30.           //if CheckRobotoBlack then begin
  31.               labels[i].font.Name:='Roboto Black';
  32.               labels[i].font.Size:=50;
  33.               labels[i].Font.Color:=clWhite;
  34.           //end;
  35.           labels[i].Show;
  36.           labels[i].Parent:=self;
  37.           labels[i].Left:=cols[x] - (labels[i].Width div 2);
  38.           labels[i].Top :=rows[y] - (labels[i].Height div 2);
  39.           inc(i);
  40.       end;
  41.     end;
  42.   end;
  43. end;                                              

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: How best to set this up - suggestions welcome!
« Reply #4 on: April 06, 2021, 10:13:45 pm »
A little further information - there is a "control interface" on the first monitor and the gameboard is on the second monitor which is the reason for passing the structure over to the gameboard to create the labels and position them on the gameboard.

Rich

Handoko

  • Hero Member
  • *****
  • Posts: 5158
  • My goal: build my own game engine using Lazarus
Re: How best to set this up - suggestions welcome!
« Reply #5 on: April 06, 2021, 10:22:08 pm »
That sounds you need to use 2 forms. I do not have experience writing programs that work on multiple monitors. But if you need to know how 2 forms can 'communicate' or exchange information, here is a demo:

https://forum.lazarus.freepascal.org/index.php/topic,38667.msg263411.html#msg263411

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: How best to set this up - suggestions welcome!
« Reply #6 on: April 06, 2021, 10:28:44 pm »
Yeah there are 2 forms already.  I have that part working.  Just mainly need a suggestion to make the labels/positioning cleaner/easier. 

As you can see by my code using a multi-dimensional array and trying to position the labels is a bit messy.  Just thinking there would be a more modern cleaner way.

The gameboard is 1920x1080 .. it's a form with a Timage on it which is used for setting the background image from a project resource.  All that is working.

I do have the categories displaying "properly" it's just if I want to move them a little bit I have to rework my whole calculation logic.

Rich

egsuh

  • Hero Member
  • *****
  • Posts: 1296
Re: How best to set this up - suggestions welcome!
« Reply #7 on: April 06, 2021, 10:40:38 pm »
Try FlowPanel (It's on the Additional tab of component palette). I don't think labels necessarily have to be TLables. You may put panels with labels on them within FlowPanel. Put all of six panels on flowpanel, and then just set visible property to true or false.
« Last Edit: April 06, 2021, 10:43:26 pm by egsuh »

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: How best to set this up - suggestions welcome!
« Reply #8 on: April 06, 2021, 10:43:21 pm »
Never used/tried FlowPanel - I will play around with that and see how it works.  Thanks for the suggestion.
Rich

Handoko

  • Hero Member
  • *****
  • Posts: 5158
  • My goal: build my own game engine using Lazarus
Re: How best to set this up - suggestions welcome!
« Reply #9 on: April 06, 2021, 10:49:53 pm »
Or maybe try this demo:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Label1: TLabel;
  16.     Label2: TLabel;
  17.     Label3: TLabel;
  18.     Shape1: TShape;
  19.     procedure FormCreate(Sender: TObject);
  20.     procedure FormResize(Sender: TObject);
  21.   private
  22.     procedure AutoCenterAll;
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. procedure TForm1.FormCreate(Sender: TObject);
  35. begin
  36.   Constraints.MinWidth  := 320;
  37.   Constraints.MinHeight := 240;
  38. end;
  39.  
  40. procedure TForm1.FormResize(Sender: TObject);
  41. begin
  42.   AutoCenterAll;
  43. end;
  44.  
  45. procedure TForm1.AutoCenterAll;
  46. begin
  47.   Label1.AutoSize  := False;
  48.   Label1.Alignment := taCenter;
  49.   Label1.Left      := 0;
  50.   Label1.Width     := Form1.Width;
  51.   Label2.AutoSize  := False;
  52.   Label2.Alignment := taCenter;
  53.   Label2.Left      := 0;
  54.   Label2.Width     := Shape1.Left;
  55.   Label3.AutoSize  := False;
  56.   Label3.Alignment := taCenter;
  57.   Label3.Left      := Shape1.Left + Shape1.Width;
  58.   Label3.Width     := Form1.Width - Label3.Left;
  59. end;
  60.  
  61. end.

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: How best to set this up - suggestions welcome!
« Reply #10 on: April 07, 2021, 03:10:41 am »
FlowPanel was promising except that I can't make it have a transparent background .. otherwise it would work perfectly. 

rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: How best to set this up - suggestions welcome!
« Reply #11 on: April 07, 2021, 03:12:00 am »
Or maybe try this demo:

I'm not sure what I'm supposed to be looking at here.  When I resize it one column stays where it is and the other one sizes.. not sure about the shape in the middle.  Am I missing something?

BTW I'm on Windows - looks like you're maybe using Linux?

Rich

Handoko

  • Hero Member
  • *****
  • Posts: 5158
  • My goal: build my own game engine using Lazarus
Re: How best to set this up - suggestions welcome!
« Reply #12 on: April 07, 2021, 04:08:20 am »
I didn't write the demo that 'solve' your problem, it only showed how to do text centering. Just as you said, the width of the first column will stay as what it is and only the second one will be resized.

The Label1 is for centering text on the form, Label2 is between the left edge of the form and the separator (TShape) and Label3 is between the separator and the right edge of the form. The calculation is relatively easy to understand, you can modify it to match your case.

Yes, I use Linux.

egsuh

  • Hero Member
  • *****
  • Posts: 1296
Re: How best to set this up - suggestions welcome!
« Reply #13 on: April 07, 2021, 04:20:40 am »
Anchorings should do that, but I haven't found any easy way to anchor against the center of the form. 

https://wiki.lazarus.freepascal.org/Anchor_Sides

Horizontal spacing is relatively easy.  Put a small hidden panel or whatever and set its anchor as centered horizontally and vertically of the form, and then anchor labels to the panel as left or right anchored. 

With vertical positioning ..  anyway need some calculations. 


rwebb616

  • Full Member
  • ***
  • Posts: 133
Re: How best to set this up - suggestions welcome!
« Reply #14 on: April 07, 2021, 04:21:26 am »
I didn't write the demo that 'solve' your problem, it only showed how to do text centering. Just as you said, the width of the first column will stay as what it is and only the second one will be resized.

The Label1 is for centering text on the form, Label2 is between the left edge of the form and the separator (TShape) and Label3 is between the separator and the right edge of the form. The calculation is relatively easy to understand, you can modify it to match your case.

Yes, I use Linux.

Ok gotcha...  I ended up creating a procedure to position the passed control based on a passed in location so inside the procedure if I pass in location 0 then that puts in one place and if I pass in position 1 that puts it in a different place.  Just used a case statement:
Code: Pascal  [Select][+][-]
  1.     case Location of
  2.       0 : begin         // Category 0 location
  3.             control.Left:=((cX div 2) - (control.width div 2));
  4.             control.Top := 450;
  5.           end;
  6.  
  7.       1 : begin         // Category 1 location
  8.             control.Left:=(cX + (cX div 2) - (control.width div 2));
  9.             control.Top := 450;
  10.           end;
cX is the center of the screen so with this example position 0 is column 1 and position 1 is column 2 - seems to work.

 

TinyPortal © 2005-2018