Jump to content
Fórum Script Brasil
  • 0
Sign in to follow this  
Guest --Sergio --

(Resolvido) FindComponent

Question

Guest --Sergio --

Ola amigos preciso trocar as propriedades de alguns campos(Dbedit)

que estão em um painel. Só que quando procuro pelos componentes

utilizando a função Painel1.FindComponent, ela não me retorna nada,

assim como Painel1.ComponentCount me retorna 0. Li em um post

que o Painel não seria um conteiner, mas então para que serviria a

sua função FindComponent? Teria uma outra forma prática de fazer

isso? A idéia e ter muitos paineis, mas alterar as propriedades daquele

que me interessar no momento e não em todos os dbedits.

Share this post


Link to post
Share on other sites

10 answers to this question

Recommended Posts

  • 0
Teria uma outra forma prática de fazer isso?

procedure TForm1.BitBtn2Click(Sender: TObject);
var i : Integer;
begin
   for i := 0 to ComponentCount -1 do
    begin
      if Components[i] is TEdit then
         TEdit(Components[i]).Enabled := false;

      if Components[i] is TBitBtn then
         TBitBtn(Components[i]).Enabled := false;
    end;
end;

Obs: o código acima deixa desabilitado os componentes descritos, mesmo que qu estejam dentro de um panel.

modifique-o para o seu propósito.

abraço

Share this post


Link to post
Share on other sites
  • 0
Guest --Sérgio --

Pois é amigo, o problema é que nessa rotina todos os

componentes Dbedits encontrados serão afetados e

no meu caso a idéia é de que apenas os que estejam

em um dado painel sofram a alteração. Talvez eu tenha

mesmo que trocar os paineis existentes por formulários.

Isso vai engordar minha aplicação, mas se tiver que ser

assim...? Só não estou entendendo porque o método

findcomponent do painel não funciona, pensei que estava

cometendo alguma bobeira. De qualquer forma, agradeço

seu interesse em me ajudar.

Um grande abraço

Share this post


Link to post
Share on other sites
  • 0
o problema é que nessa rotina todos os

componentes Dbedits encontrados serão afetados e

no meu caso a idéia é de que apenas os que estejam

em um dado painel sofram a alteração.

Então procure pelo componente que quer, e execute a ação somente em cima dele

exemplo:

procedure TForm1.Button1Click(Sender: TObject);
var i : Integer;
begin
   for i := 0 to ComponentCount -1 do
    begin
      if Components[i] is TComboBox then
         showmessage(inttostr(i));

      if i = 3 then
         TComboBox(Components[3]).Enabled := false;
    end;

end;

abraço

Share this post


Link to post
Share on other sites
  • 0
Guest --Sérgio --

Deixa eu te explicar melhor: Tenho um PageControl com vários

Tabsheets e a alguns tbsheets tem um ou mais paineis. Cada

um desses cinteiners tem dbedits que se referenciam a própositos

distintos. Em um dado momento apenas os dbedits de um painel

deverão estar em modo de edição. Outra solução que me ocorreu

agora, seria qualificar cada grupo com prefíxos que os distinguissem

dos demais, assim eu poderia percorrer o formulário com o método

findcomponent buscando pelo seus nomes e não por suas classes.

Share this post


Link to post
Share on other sites
  • 0
Pois é amigo, o problema é que nessa rotina todos os componentes Dbedits encontrados serão afetados e no meu caso a idéia é de que apenas os que estejam em um dado painel sofram a alteração.
Sérgio, vou supor que sua necessidade seja a mesma que já tive - desabilitar componentes dentro de um GroupBox.

Quando se desabilita um Panel ou GroupBox, os seus componentes ficam impossibilitados de serem acessados, entretanto, visualmente nada muda dando a impressão que estão ativos. Então, desabilitando os componentes dentro destes componentes, conseguimos que eles fiquem grayed (acinzentados) - dando o retorno visual. Outra possibilidade é manipular a propriedade ReadOnly dos componentes.

Segue uma versão enxuta de procedure que tenho em minha unit de utilidades. A idéia básica é que procuramos em nosso form todos os componentes que estão dentro de Panel ou GroupBox. No seu caso, teremos que verificar se a classe é TDBEdit:

// GroupControl = componente que agrupa componentes - TPanel, TGroupBox, TTabSheet, TTabbedNotebook ...
// Enable = ação. Pode ser habilitar (true) ou desabilitar (false)
procedure EnableGroupedControls(GroupControl :TControl; Enable :Boolean);
var
  Idx :Integer;
  Form :TForm;
  Control :TComponent;
begin
 // Vamos a "caça" do Form onde o componente está
  Control := GroupControl.Parent;
  while not (Control is TForm) and (Control.GetParentComponent <> nil) do
    Control := Control.GetParentComponent;
  Form := Control as TForm;

 // Com o Form em "mãos", varremos seus componentes
 // procurando por componentes com a característica desejada,
 // ou seja, que esteja no GroupControl 
  for Idx := 0 to Form.ComponentCount -1 do
  begin
    Control := Form.Components[Idx].GetParentComponent;
    if Assigned(Control) and ((Control.Owner = GroupControl) or (Control = GroupControl)) then
      (Form.Components[Idx] as TControl).Enabled := Enable;
    // ou se for atualizar a propriedade ReadOnly
    //  (Form.Components[Idx] as TControl).ReadOnly := Enable;
  end;
end;
O uso no código:
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  EnableGroupedControls(Panel1, False);
// ou
//  EnableGroupedControls(TabSheet1, False);
// e assim por diante
end;

Só não estou entendendo porque o método findcomponent do painel não funciona, ...
Se você se atentar para o fato de que todos os componentes adicionados ao form, em design-time, o tem como Owner, você entenderá que basicamente há uma única lista de componentes - aquela acessada pela propriedade Components do Form em questão!

Logo, se for utilizar o método FindComponent, este deverá ser o do Form e não o do Panel.

A Borland deve ter tido um motivo para fazer as coisas deste modo (eu até teria um palpite, mas isso não é relevante).

A questão: "o componente que está dentro do Panel" é apenas uma condição visual, e sendo assim, quem determina onde o componente aparece é a propriedade Parent deste. Eu já usei deste artifício para criar um cadastro simples com 10 TabSheets e apenas 1 DBGrid e 3 Botões (Incluir, Alterar/Gravar, Excluir/Cancelar) - trocando o dataset conforme a guia era selecionada e setando o Parent destes componentes para a guia selecionada.

Contudo, nada impede que, criando componentes em run-time, você defina um Owner que não seja o Form (motivo pelo qual apareceu na minha função o teste: Control.Owner = GroupControl).

Abraços

Share this post


Link to post
Share on other sites
  • 0
Guest --Sergio --

É meu grande, você acertou na mosca, meu problema é exatamente

o que teve. Percorri muito antes de recorres a esta lista, mas não

obtive êxito. Realmente tenho um form com um PageControl com

algumas tabsheet que possuem outros PageControls dentro destas

e esse, por sua vez, posssue outros tabsheets que dentro tem um ou

dois paineis que, por fim, contém os componentes de edição do banco de

dados. Mas apenas um conjunto de botões com procedimentos para

todas as abas. Parece complicado, mas foi uma forma de organizar

meu projeto, que à mim, parece bem mais simples à usar vários forms.

Mas os componentes de edição devem permanecer em readonly até

que o botão de inclusão ou edição sejam pressionados. E para complicar

mais um pouquinho, ainda permitirei que mais de um conjunto de

componentes contido em mais de um painel, possam ser manipulados

simultaneamente. Mas o segredo, desvendado por você, esta na

propriedade parent, que realmente ainda não tinha tentado.

Estou muito grato, de verdade!

Um grande abraço.

Share this post


Link to post
Share on other sites
  • 0
Guest --Sérgio --

Só para finalizar: Obtive êxito e a rotina ficou simplesmente assim:

procedure TForm1.SpeedButton19Click(Sender: TObject);
var
 Idx :Integer;
 Control : TComponent;
begin
  for Idx := 0 to ComponentCount -1 do
  begin
    if Components[Idx].ClassType = TDBedit then
    begin
      Control := Components[Idx].GetParentComponent;
      if Control = Panel1 then
        Datamodule2.ZQueryClientes.RequestLive := False;
    end;
  end;
end;

Tive apenas um pequeno problema quando segui a dica do amigo Jhonas,

mas já esta resolvido. Minha intenção era habilitar ou desabilitar, para

edição, determinados componentes que estivessem em um painel, mas que

sua visibilidade não fosse alterada quando houvesse a troca de seu estado.

Isso, para que o operador tivesse conforto visual em qualquer dos estados do

componente. A princípio a instrução correta, pelo menos seguindo a minha

lógica de programação, seria:

(Components[idx] as TControl).ReadOnly:= false;

O problema e que, apesar da propriedade ReadOnly dos DBEdits estar disponível

para manipulação no Objet Inspector, não é autocomplementada pelo Delphi e,

se colocado forçadamentena na linha de comando, apresenta um erro em sua

compilação. A solução foi manipular a propriedade RequestLive da Query de

ligação entre o componente e o banco de dados, que pelo menos no meu caso,

não fez diferença.

Edited by Micheus
Adicionado o delimitador de código [code] [/code]

Share this post


Link to post
Share on other sites
  • 0

Para não ficar incompleta a questão...

A princípio a instrução correta, pelo menos seguindo a minha

lógica de programação, seria:

(Components[idx] as TControl).ReadOnly:= false;

O problema e que, apesar da propriedade ReadOnly dos DBEdits estar disponível para manipulação no Objet Inspector, não é autocomplementada pelo Delphi e, se colocado forçadamentena na linha de comando, apresenta um erro em sua compilação.

Sérgio, a razão para a falta do "auto-completamento" deve-se ao fato de que você está fazendo um cast do componente (TComponent) para a class TControl.

Se você verificar no help, notará que a propriedade em questão não está disponível para esta classe. Assim, considerando o fato de que você está procurando por uma classe específica (inclusive, você testa ela), você deveria ter feito o cast do componente para esta classe, ou seja TDBEdit, onde o código ficaria:

(Components[idx] as TDBEdit).ReadOnly:= false;

A título de maior generalização de uma função, tenta-se utilizar a classe mais abrangente possível (aquela com maior número de sub-classe, com suporte a determinada propriedade ou método) - é o caso do acesso á propriedade Enabled e Visible. O importante é conhecer que propriedades e métodos cada Classe possui para poder estruturar da melhor maneira um procedimento como este.

A solução foi manipular a propriedade RequestLive da Query de ligação entre o componente e o banco de dados, que pelo menos no meu caso, não fez diferença.
Exatamente, neste seu caso pode não fazer diferença, entretanto, se um dataset tiver campos que possam ser manipulados em um panel e outros campos em outro panel e neste último não possam ser alterados, então teria mesmo que usar a solução de atuação sobre os TDBEdits.

Abraços

Share this post


Link to post
Share on other sites
  • 0
Guest --Sérgio --

Não tenho nem o que falar, mas se pedir desculpas ajudar...

que furo o meu. É claro que tem que ser TDBedit e funciona.

Bom, pelo menos, já tenho duas soluções. Entretanto,

mudando a da query, me facilita pelo fato de que os DBEdits

permanecem sem alteração da cor dos caracteres, mas ainda

assim, não editáveis.

Mais uma vez, obrigado.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  



  • Forum Statistics

    • Total Topics
      148561
    • Total Posts
      644241
×
×
  • Create New...