Using Firemonkey I have a TVertScrollBox which contains a TPanel which gets dynamically populated with a number of the following TDisplayItem objects.
The problem is that the TDisplayItem’s don’t size properly so the text on the various components is superimposed etc.
I can fix this on the items that are in the visible area of the scrollbox by by getting the sizes of the component parts and making the containers that size etc. I’ve tried refreshing and application.ProcessMessages to get everything to resize as well as various alignment and warp options but to no avail.
Hopefully I’ve missed a key factor in this and haven’t unearthed a Firemonkey limitation!
Cheers,
Martin.
Constructor TDisplayItem.Create(owner : TComponent);
begin
inherited Create(owner);
Align := TAlignLayout.alTop;
pnlLabels := TPanel.Create(nil);
pnlLabels.Align := TAlignLayout.alTop;
pnlLabels.Height := 50;
pnlLabels.Parent := self;
lblICAO := TLabel.Create(nil);
lblICAO.Parent := pnlLabels;
with lblICAO do
begin
text := 'ICAO';
Height := 30;
Position.X := 10;
align := TAlignLayout.alTop;
TextAlign := TTextAlign.taCenter;
Font.Size := 18;
FontColor := $FF00D000 ;
Visible := False;
StyledSettings := [TStyledSetting.ssFamily];//, TStyledSetting.ssFontColor];
end;
lblFrom := TLabel.Create(nil);
lblFrom.Parent := pnlLabels;
with lblFrom do
begin
text := 'From : ';
Height := 30;
Position.X := 10;
Position.y := 2;
width := 150;
FontColor := $FFFF0000 ;
StyledSettings := [TStyledSetting.ssFamily];//, TStyledSetting.ssFontColor];
end;
lblTo := TLabel.Create(nil);
lblTo.Parent := pnlLabels;
with lblTo do
begin
text := 'To : ';
Height := 30;
Position.X := 170;
Position.y := 2;
width := 150;
FontColor := $FFFF0000 ;
StyledSettings := [TStyledSetting.ssFamily];//, TStyledSetting.ssFontColor];
end;
lblStatus := TLabel.Create(nil);
lblStatus.Parent := pnlLabels;
with lblStatus do
begin
text := 'Status : ';
Height := 30;
Position.X := 330;
Position.y := 2;
width := 100;
Font.Size := 10;
FontColor := $FFFF0000 ;
StyledSettings := [TStyledSetting.ssFamily];//, TStyledSetting.ssFontColor];
end;
lblNonGeog := TLabel.Create(nil);
with lblNonGeog do
begin
text := 'Non-Geog : ';
Height := 30;
Position.X := 440;
Position.y := 2;
width := 150;
Font.Size := 10;
FontColor := $FFFF0000 ;
StyledSettings := [TStyledSetting.ssFamily];//, TStyledSetting.ssFontColor];
end;
lblNonGeog.Parent := pnlLabels;
memItem := TLabel.Create(nil);
memItem.Parent := self;
with memItemE do
begin
Align := TAlignLayout.alTop;
DisableFocusEffect := False;
AutoSize := True;
WordWrap := True;
end;
OK, finally solved it. I was on the right lines thinking it was a drawing issue - when the text of one of the labels was changed a label.dopaint was needed. This then updated the height of the label even if it was not in the display area. The paraent TPanel could then have it's height set correctly by summing the heights of the child components.
Related
When I create objects at runtime in FireMonkey, some lines are shown on the sides of the objects.
The image below is a TLayout. When I resize the Form or move the mouse, the lines disappear. This happens with TImage, TRectangle, TLayout, and other components.
Can someone give me a solution for this graphic problem?
TLayout showing the lines:
TLayout after resizing the Form:
var
backRectangle: TRectangle;
category, title: TLabel;
icon: TImage;
bar: TRectangle;
background: TGridPanelLayout;
lay1, layicon: TLayout;
begin
backRectangle := TRectangle.Create(Self);
with backRectangle do
begin
Height := 150;
Align := TAlignLayout.top;
Fill.Color := Talphacolors.White;
Parent := Self;
Stroke.Thickness := 0;
Margins.Left := 20;
Margins.Top := 20;
Name := 'rectangle';
end;
background := TGridPanelLayout.Create(backRectangle);
with background do
begin
Parent := backRectangle;
Align := TAlignLayout.Client;
ColumnCollection.ClearAndResetID;
ColumnCollection.BeginUpdate;
with ColumnCollection.Add do
begin
Value := 100;
SizeStyle := TGridPanelLayout.TSizeStyle.Percent;
end;
ColumnCollection.EndUpdate;
RowCollection.Clear;
end;
lay1 := TLayout.Create(backRectangle);
lay1.Parent := backRectangle;
lay1.Align := TAlignLayout.client;
background.AddObject(lay1);
layicon := TLayout.Create(lay1);
layicon.Parent := lay1;
layicon.Align := TAlignLayout.client;
category := TLabel.Create(backRectangle);
with category do
begin
StyledSettings := [];
AutoSize := true;
Parent := lay1;
Align := TAlignLayout.None;
BeginUpdate;
TextSettings.BeginUpdate;
TextSettings.Font.Family := 'Roboto';
TextSettings.Font.Style := [TFontStyle.fsBold];
TextSettings.Font.Size := 16;
Text := 'category';
TextSettings.EndUpdate;
Margins.Left := 25;
Margins.Right := 0;
Margins.Bottom := 6;
Margins.Top:= 10;
TabOrder := 0;
end;
bar := TRectangle.Create(backRectangle);
bar.Width := 100;
bar.Height := 3;
bar.Fill.Color := $FF518CD2;
bar.Parent := lay1;
bar.Align := TAlignLayout.None;
bar.Stroke.Thickness := 0;
bar.Margins.Right := 20;
icon := timage.Create(layicon);
with icon do
begin
Parent := lay1;
Width := 30;
Margins.Left := 20;
Margins.Right := 20;
Margins.Bottom := 15;
Margins.Top := 45;
WrapMode := TImageWrapMode.fit;
Align := TAlignLayout.FitLeft;
try
Bitmap.LoadFromFile('icon');
except
end;
end;
title := TLabel.Create(layicon);
with title do
begin
StyledSettings := [];
Parent := lay1;
Text := '';
Align := TAlignLayout.Client;
TextSettings.Font.Family := 'Roboto';
TextSettings.Font.Style := [];
TextSettings.Font.Size := 16;
Margins.Left := 10;
TextSettings.VertAlign := TTextAlign.Center;
end;
bar.Align := TAlignLayout.Top;
category.Align := TAlignLayout.Top;
end;
I´m designing a new VCL component using a set of existing TControls.
The controls are placed on TPanels, some aligned to left position, one to the right position and finally one to the client area. Each of those panels has the customized component as it´s parent.
I need to place splitters between the panels, in order for the users to be able to resize the inner components.
The problem is, I simply can´t figure out the logic applied to the positioning of the splitters when created at runtime.
I visited quite a number of forums, each pointing to a different solution, but none of them worked.
Tried to:
1 - when creating the splitters, use the properties "lef"t and "width" of the component where it should be positioned aside, as its "left" property.
2 - Use the left property to assign the position where it should be.
and some others I can´t remember.
What am I missing?
In the code below, the splitters abre being created where it should be.
Just after the corresponding panel, and theirs left property corresponds to the last thing i´ve tried (it´s position).
constructor TDBIDBGridFilterBar.Create(AOwner: TComponent);
begin
inherited;
Self.Width := 490;
Self.Height := 23;
Self.Constraints.MinWidth := 285;
if fComboColunasWidth = 0 then
fComboColunasWidth := 118;
fBackGroundPanel := TPanel.Create(Self);
fBackGroundPanel.Parent := Self;
fBackGroundPanel.ShowCaption := false;
fBackGroundPanel.BevelOuter := bvNone;
fBackGroundPanel.Align := alClient;
fButtonsPanel := TPanel.Create(Self);
fButtonsPanel.Parent := fBackGroundPanel;
fButtonsPanel.ShowCaption := false;
fButtonsPanel.BevelOuter := bvNone;
fButtonsPanel.Width := 73;
fButtonsPanel.Align := alLeft;
fBtnMarcaTodos := TButton.Create(Self);
fBtnMarcaTodos.Parent := fButtonsPanel;
fBtnMarcaTodos.Width := 23;
fBtnMarcaTodos.Height := 23;
fBtnMarcaTodos.Left := 0;
fBtnMarcaTodos.Hint := 'Marcar todos';
fBtnMarcaTodos.ShowHint := true;
fBtnDesmarcaTodos := TButton.Create(Self);
fBtnDesmarcaTodos.Parent := fButtonsPanel;
fBtnDesmarcaTodos.Width := 23;
fBtnDesmarcaTodos.Height := 23;
fBtnDesmarcaTodos.Left := 23;
fBtnDesmarcaTodos.Hint := 'Desarcar todos';
fBtnDesmarcaTodos.ShowHint := true;
fBtnInveteSelecao := TButton.Create(Self);
fBtnInveteSelecao.Parent := fButtonsPanel;
fBtnInveteSelecao.Width := 23;
fBtnInveteSelecao.Height := 23;
fBtnInveteSelecao.Left := 46;
fBtnInveteSelecao.Hint := 'Inverter seleção';
fBtnInveteSelecao.ShowHint := true;
fLabelPanel := TPanel.Create(Self);
fLabelPanel.Parent := fBackGroundPanel;
fLabelPanel.Width := 33;
fLabelPanel.Align := alLeft;
fLabelPanel.ShowCaption := false;
fLabelPanel.BevelOuter := bvNone;
fLabel := TLabel.Create(Self);
fLabel.Parent := fLabelPanel;
fLabel.Top := 4;
fLabel.Left := 4;
fLabel.Caption := 'Filtro:';
fLabel.Width := 28;
fComboColunasPan := TPanel.Create(Self);
fComboColunasPan.Parent := fBackGroundPanel;
fComboColunasPan.ShowCaption := false;
fComboColunasPan.BevelOuter := bvNone;
fComboColunasPan.width := fComboColunasWidth;
fComboColunasPan.Align := alLeft;
fComboColunas := TDBIComboBox.Create(Self);
fComboColunas.Parent := fComboColunasPan;
fComboColunas.Text := '';
fComboColunas.OnEnter := PopulaComboColunas;
fComboColunas.OnChange := ComboChange;
fComboColunas.Style := csOwnerDrawFixed;
fComboColunas.Align := alClient;
fComboColunas.Hint := 'Colunas';
fComboColunas.ShowHint := true;
fSplitterColunas := TSplitter.Create(Self);
fSplitterColunas.Parent := fBackGroundPanel;
fSplitterColunas.Align := alLeft;
fSplitterColunas.Left := 1;
fComboOperadorPan := TPanel.Create(Self);
fComboOperadorPan.Parent := fBackGroundPanel;
fComboOperadorPan.ShowCaption := false;
fComboOperadorPan.BevelOuter := bvNone;
fComboOperadorPan.width := fComboColunasWidth;
fComboOperadorPan.Align := alLeft;
fComboOperador := TDBIComboBox.Create(Self);
fComboOperador.Parent := fComboOperadorPan;
// fComboOperador.Items.Add(cItensComboFiltro);
fComboOperador.Style := csOwnerDrawFixed;
fComboOperador.Align := alClient;
fComboOperador.Hint := 'Comparação';
fComboOperador.ShowHint := true;
fComboOperador.Text := ' = ';
fSplitterOperador := TSplitter.Create(Self);
fSplitterOperador.Parent := fBackGroundPanel;
fSplitterOperador.Align := alLeft;
fSplitterOperador.Left := 2;
fBtnAdcFiltroPan := TPanel.Create(Self);
fBtnAdcFiltroPan.Parent := fBackGroundPanel;
fBtnAdcFiltroPan.ShowCaption := false;
fBtnAdcFiltroPan.BevelOuter := bvNone;
fBtnAdcFiltroPan.width := 23;
fBtnAdcFiltroPan.Align := alRight;
fBtnAdcFiltro := TButton.Create(Self);
fBtnAdcFiltro.Parent := fBtnAdcFiltroPan;
fBtnAdcFiltro.Height := 23;
fBtnAdcFiltro.Width := 23;
fBtnAdcFiltro.Caption := '+';
fBtnAdcFiltro.Hint := 'Adicionar filtro...';
fBtnAdcFiltro.ShowHint := true;
fBtnAdcFiltro.OnClick := btnNewFilterClick;
fClientPanel := TPanel.Create(Self);
fClientPanel.Parent := fBackGroundPanel;
fClientPanel.ShowCaption := false;
fClientPanel.BevelOuter := bvNone;
fClientPanel.Align := AlClient;
fMaskEdit := TDBIMaskEdit.Create(Self);
fMaskEdit.Parent := fClientPanel;
fMaskEdit.Font.Size := 9;
fMaskEdit.Align := alTop;
end;
When you add the panels to the background panel in left to right order, it is sufficient to set the Left property of the added panels before you set the Alignment property, to a large enough value, so it exceeds the Left property of components already placed on the background panel. The value you set can even be bigger than the width of the background panel.
When you add panels or other components in a right to left order (Alignment = alRight;) you can leave the Left property as 0.
The above is true for any component you place on the background panel, also splitters. When using splitters, you probably also want to set the neighbouring components Constraints.MinWidth property to something like e.g. 10 to prevent the component width to accidentally be reduced to zero, and therefore become invisible. Once that happens there's no way to get it visible again with the splitter.
For example, this code:
procedure TForm1.Panel1Click(Sender: TObject);
var
i: integer;
begin
i := 1;
repeat
with TPanel.Create(self) do
begin
Parent := Panel1;
Left := 510;
Align := alLeft;
Width := 40;
Constraints.MinWidth := 10;
Caption := 'L'+IntToStr(i);
end;
if (i = 3) or (i = 5) then
with TSplitter.Create(self) do
begin
Parent := Panel1;
Left := 510;
Width := 10;
Align := alLeft;
end;
inc(i);
until i > 5;
with TPanel.Create(self) do
begin
Parent := Panel1;
Width := 40;
Align := alRight;
Caption := 'R1';
end;
with TPanel.Create(self) do
begin
Parent := Panel1;
Width := 40;
Align := alRight;
Caption := 'R2';
end;
with TPanel.Create(self) do
begin
Parent := Panel1;
Left := 510;
Align := alClient;
Caption := 'C';
end;
end;
produces this design:
L1 .. L5 are alLeft aligned, C is alClient aligned and R1 .. R2 are alRight aligned.
I managed to figure it out.
Since all the components created before are left aligned, their left property are set to 0, no matter where in the form they are located.
So, in order to fix the problem, i had to propperly fill the left property of the previous panels.
fThisPanel.left := fPreviousPanel.Left + fPreviousPanel.width + 1, and so on ...
How the change the height of a cxProgressBar?
I've tried this but no luck so far:
var
cxProgressBar1: TcxProgressBar;
begin
cxProgressBar1 := TcxProgressBar.Create(Self);
with cxProgressBar1 do
begin
Parent := Self;
Position := 22;
Width := 113;
Height := 120;
Properties.Orientation := cxorVertical;
end;
end;
The height remains the same.
I forgot to set AutoSize := false; before setting Width and/or Height
So this is the solution :
var
cxProgressBar1: TcxProgressBar;
begin
cxProgressBar1 := TcxProgressBar.Create(Self);
with cxProgressBar1 do
begin
AutoSize := false;
.....
end;
end;
I am programming a program where you have to enter a password into a InputBox to gain access to the programs min features . But I have a problem if you click on cancel on the inputbox my program gives a error message . So i wanted to know if any one know how I can get that right because with the Messagedlg I know you use IF . But how can I get it right with a InputBox ?
InputBox() returns a blank string if the dialog is canceled, eg:
var
Pass: String;
Pass := InputBox('Password needed', 'Enter the password:');
if Pass <> '' then
begin
// use Pass as needed...
end;
Alternatively, use InputQuery() instead, which returns a Boolean to indicate whether the dialog was canceled or not, eg:
var
Pass: String;
if InputQuery('Password needed', 'Enter the password:', Pass) then
begin
// use Pass as needed...
end;
Many times it is better to have a custom InputQuery
function InputValor(const aCaption: String; APrompt: string; var aValor:
String): Boolean;
var
vForm : TForm;
vLabel : TLabel;
vBtnOk : TBitBtn;
vValor : TEdit;
vBtnCancel : TBitBtn;
begin
Result := False;
vForm := TForm.Create(Application);
vLabel := TLabel.Create(vForm);
vValor := TEdit.Create(vForm);
vBtnOk := TBitBtn.Create(vForm);
vBtnCancel := TBitBtn.Create(vForm);
with vForm do
begin
Name := 'frmValor';
Position := poScreenCenter;
BorderIcons := [biSystemMenu];
BorderStyle := bsDialog;
Caption := aCaption;
ClientHeight := 150;
ClientWidth := 515;
Color := clBtnFace;
OldCreateOrder := False;
Font.Charset := DEFAULT_CHARSET;
Font.Color := clWindowText;
Font.Height := -11;
Font.Name := 'Tahoma';
Font.Style := [];
OldCreateOrder := False;
PixelsPerInch := 96;
Left := 0;
Top := 0;
end;
with vLabel do
begin
Name := 'vLabel';
Parent := vForm;
AutoSize := False;
Left := 18;
Top := 15;
Width := 484;
Height := 41;
Caption := APrompt;
WordWrap := True;
end;
with vValor do
begin
Name := 'vValorEdit';
Parent := vForm;
Left := 18;
Top := 62;
Width := 484;
Height := 21;
Text := '';
end;
with vBtnOk do
begin
Name := 'vBtnOk';
Parent := vForm;
Caption := 'Aceptar';
Left := 335;
Top := 103;
Width := 75;
Height := 25;
TabOrder := 1;
ModalResult := mrOk;
end;
with vBtnCancel do
begin
Name := 'vBtnCancel';
Parent := vForm;
Caption := 'Cancelar';
Left := 427;
Top := 103;
Width := 75;
Height := 25;
TabOrder := 2;
ModalResult := mrCancel;
end;
vForm.ShowModal;
if (vForm.ModalResult = mrOk) and (vValor.Text <> '') then
begin
Result := True;
aValor := vValor.Text;
end else
begin
Result := False;
aValor := '';
end;
FreeAndNil(vForm);
end;
Use in the same way as the Official:
var
vTest : String;
begin
if (InputValor('Title', 'Label text', vTest) = True) then
ShowMessage(vTest);
end;
I have a little problem. I'm trying to create a TPaintBox on a TPanel like this:
procedure TForm1.mkPaint(S: string);
var PB: TPaintBox;
begin
PB := TPaintBox.Create(Self);
with PB do
begin
Parent := Panel1;
Visible := True;
Name := S;
Height := 100;
Width := 100;
Left := 8;
Top := 8;
// ParentColor := False;
Brush.Style := bsSolid;
Brush.Color := $00000000;
end;
Application.ProcessMessages;
end;
Now, if i change the PaintBox's Parent to Form1, i can see the brush.
But, with parent changed to Panel1, nothing happens. Any idea of how can i fix this?
Thanks in advance!
Is the TPanel visible to begin with?
Also, TPaintBox does not have a public Brush property (perhaps you are thinking of TShape?). TWinControl does, but TPaintBox is not a TWinControl descendant. It is a TGraphicControl descendant.
Yeah that was a mistake of mine. I changed the code to:
pb := TPaintBox.Create(self);
with pb do begin
Parent := Form1;
Visible := true;
Top := 1;
Left := 1;
Width := 250;
Height := 100;
ParentColor := false;
Canvas.Brush.Color := clBlack;
Canvas.Font.Size := 12;
Canvas.Font.Color := clWhite;
Canvas.FillRect(ClientRect);
Canvas.TextOut(1, 1, 'test');
end;
but without success.. i mean, if i drop a PaintBox component to the form then the code is taking effect as it should do, but dynamically creating a TPaintBox.... dunno.