TreeView Editável.. É possível??

Delphi

18/06/2004

Bom dia Pessoal,


Minha TreeView está assim:

  Texto
    |-Igual 
        |- x


Eu tava querendo saber se tem jeito do usuário escrever nessa treeView, mais precisamente no lugar do [b:e6b2e6873d]X[/b:e6b2e6873d]. Ou se tem algum componente melhor pra fazer isto....

Qualquer Ajuda é muito bem vinda...

Lucas!


Lucas Silva

Lucas Silva

Curtidas 0

Respostas

Vinicius2k

Vinicius2k

18/06/2004

Lucas,

Escrever na TreeView é relativamente simples, mas o que eu não entendi é se vai haver interação do usuário em informar qual item ele quer editar (através de seleção)...

Se sim, por exemplo :
procedure TForm1.Button1Click(Sender: TObject);
begin
  TreeView1.Items[TreeView1.Selected.AbsoluteIndex].Text:= Edit1.Text;
end;


Se não vc precisará armazenar em uma variável o AbsoluteIndex do node que vc quer editar e aplicar no Items[xxx] da rotina acima...

É isso q vc precisa?

T+


GOSTEI 0
Lucas Silva

Lucas Silva

18/06/2004

2k,
O que eu estou querendo é o usuario clicar e alterar um dado na treeview,
se possível escrevendo nela mesmo....

Vamos supor que eu tenha a treeview:

     Nome
       |- Igual 
         |- Lucas


Tem jeito de clicar na palavra [b:22f9e6eb61]Lucas[/b:22f9e6eb61], e sair editando???

Não sei se isso é possível...


GOSTEI 0
Vinicius2k

Vinicius2k

18/06/2004

Entendi... bem, com o TreeView convencional não conheço... e me arriscaria a dizer q não tem jeito, mas posso estar enganado...

Acho que seria melhor para esta situação vc procurar por algum componente de 3º que tenha esta funcionalidade...

T+


GOSTEI 0
Lucas Silva

Lucas Silva

18/06/2004

Entendi... bem, com o TreeView convencional não conheço... e me arriscaria a dizer q não tem jeito, mas posso estar enganado... Acho que seria melhor para esta situação vc procurar por algum componente de 3º que tenha esta funcionalidade... T+


Valeu...
Vou dar uma procurada aqui...


GOSTEI 0
Nildo

Nildo

18/06/2004

Lucas, use o método:

TreeView1.Selected.EditText;


GOSTEI 0
Vinicius2k

Vinicius2k

18/06/2004

Lucas, use o método: TreeView1.Selected.EditText;


:oops: comprovado que eu estava enganado...
pensando bem, seria muito estranho a TreeView não ter este recurso mesmo...


GOSTEI 0
Xanatos

Xanatos

18/06/2004

Bom...nao precisa de mudar nada pra editar é só mudar a propriedade readonly para false! e voce mudar como um arquivo ou pasta do windows!


GOSTEI 0
Michael

Michael

18/06/2004

Olá amigo Lucas!

O componente TTreeView tem a propriedade ReadOnly que define se os labels dos seus itens serão editáveis ou não. Se esta propriedade for setada para false, então quando o usuário der um clique sobre um ítem selecionado da lista o Windows permitirá a sua edição. Uma desvantagem decorrente deste procedimento é que todos os ítens poderão ser alterados pelo usuário. Em alguns casos é necessário que apenas determinados itens sejam editáveis, e outros não. Infelizmente os objetos TTreeNode não tem uma propriedade ReadOnly individual, o que facilitaria em muito o trabalho. Mas como pessoalmente o Delphi é a ferramenta mais flexivél que existe, nada o que um pouco de código não resolva não é?

Imagine que você tenha o seguinte TreeView:

Cadastro
  |- Dados pessoais
          |- Nome
      |- Michael Benford


Apenas o nome ´Michael Benford´ deveria ser editável, e não os outros. Para que isso seja possível, basta adicionar no evento OnClick do TreeView:

procedure TForm1.TreeView1Click(Sender: TObject);
begin
  { Evita que seja gerado um erro de Access Violation se nada foi   selecionado }
  if TreeView1.Selected = nil then exit;

  TreeView1.ReadOnly := not (TreeView1.Selected.Level = 3);
end;


O ´macete´ aqui é utilizar a propriedade Level do TTreeNode para saber em qual nível nosso ítem está localizado. Como a contagem começa de 0, então nosso nome está no nível 3. Existem outras maneiras de se obter o mesmo resultado, como utilizar a propriedade ImageIndex do TreeNode, caso você defina uma imagem personalizada para esse nível. Você ainda poderia utilizar também outra propriedade, HasChildren, que informa se o ítem tem ´filhos´ ou não. Assim, somente os ítens do último nível serão editados. Nosso exemplo ficaria assim:

procedure TForm1.TreeView1Click(Sender: TObject);
begin
  { Evita que seja gerado um erro de Access Violation se nada foi selecionado }
  if TreeView1.Selected = nil then exit;

  TreeView1.ReadOnly := TreeView1.Selected.HasChildren;
end;


Esta abordagem talvez seja a mais prática, mas somente, como já dito, os últimos ítens serão editáveis. A vantagem é que você não terá que se preocupar em contar os nívels (Levels) de cada ítem.

Espero ter ajudado amigo! Qualquer dúvida, estamos aí.

Abraços!


GOSTEI 0
Lucas Silva

Lucas Silva

18/06/2004

Ótimo pessoal...
Funcionou legal...

Só mais uma dúvida aqui.
procedure TForm1.TreeView1Click(Sender: TObject);
begin
  { Evita que seja gerado um erro de Access Violation se nada foi selecionado }
  if TreeView1.Selected = nil then exit;


  if TreeView1.Selected.Level = 2 then
   TreeView1.Selected.EditText;
end;


Com este código quando clico no nivel 2 do TV ele deixa para a edição.

Quando digito alguma coisa e clico em outro TreeNode ele não sai (fica com o foco só no TreeNode editável (de nível 2) ), a não ser que eu dê um enter no TreeNode de nível 2, e depois clique em outro TreeNode;

Alguem já passou por isto??

Lucas!


GOSTEI 0
Vinicius2k

Vinicius2k

18/06/2004

Lucas,
o que o colega xanatos sugeriu eu sabia, mas imaginei que vc não quisesse tornar todos os ítens editáveis...

bem, então pode-se aliar a isso a ténica do colega michel, mas talvez de uma forma mais simples...

sem usar o OnClick... seria o método convencional do windows de um click depois outro para entrar em edição (não duplo)... vc protegeria o nível que pode ser editado no evento OnEditing, dessa forma, por exemplo:
procedure TForm1.TreeView1Editing(Sender: TObject; Node: TTreeNode;
  var AllowEdit: Boolean);
begin
  if Node.Level < 2 then AllowEdit:= False; //só permite edição no level 3
end;

também pode usar a leitura da propriedade HasChildrens para permitir a edição apenas de quem não tem filhos, ou seja, o último...

creio que ficaria sem este problema que vc está enfrentando agora...
T+


GOSTEI 0
Xanatos

Xanatos

18/06/2004

Ou voce pode usar o ImageIndex como se fosse uma tag e no evento onEditing!

  if Node.ImageIndex <> 1 then
    AllowEdit:= false;


8)


GOSTEI 0
Lucas Silva

Lucas Silva

18/06/2004

Gostaria que quando o usuário abrisse o Node ele já viria em codições de edição.
Este código que você me passou ai 2k, tem um problema (não é bem um problema), o usuário tem que abrir o node, clicar em cima dele 2 vezes, e ai sim ele abre para edição...

Teria jeito que resolver isto?


GOSTEI 0
Michael

Michael

18/06/2004

Para fazer o que você quer precisamos salvar o item que está selecionado e então verificar no momento da edição se ele não foi o último membro da TreeView que foi modificado: Eis o procedimento adequado para o seu propósito Lucas:

procedure TForm1.TreeView1Click(Sender: TObject);
{$J+}
const UltimoItemEditado : TTreeNode = nil;
{$J-}
begin
  { Evita que seja gerado um erro de Access Violation se nada foi selecionado }
  if TreeView1.Selected = nil then exit;

  { Permite a edição apenas se o item selecionado estiver no nivel 2 }
  TreeView1.ReadOnly := not (TreeView1.Selected.Level = 2);

  if not TreeView1.ReadOnly and (TreeView1.Selected <> UltimoItemEditado) then
    begin
      UltimoItemEditado := TreeView1.Selected;
      TreeView1.Selected.EditText;
    end;
end;


Era assim que você queria que funcionasse?

Ao amigo Vinicius2k: meu nome é Michael, e não Michel! ;-)

Abraços!


GOSTEI 0
Lucas Silva

Lucas Silva

18/06/2004

Funcionou sim.
Agora só falta alguns ajustes aqui..

Qual é a função dos [b:cb97f79fec]{$J+} [/b:cb97f79fec]e [b:cb97f79fec]{$J-}[/b:cb97f79fec]
{$J+} 
const UltimoItemEditado : TTreeNode = nil; 
{$J-} 

Notei que se não colocar dá um erro de código.


GOSTEI 0
Nildo

Nildo

18/06/2004

voce quer editar com condição? é facil...

no evento OnEditing você coloca assim:

AllowEdit := (Condicao);

E você pode usar o objeto NODE deste evento. Por exemplo:

AllowEdit := ( Node.text = ´tal´ );


GOSTEI 0
Lucas Silva

Lucas Silva

18/06/2004

voce quer editar com condição? é facil... no evento OnEditing você coloca assim: AllowEdit := (Condicao); E você pode usar o objeto NODE deste evento. Por exemplo: AllowEdit := ( Node.text = ´tal´ );


Tranquilo nildo, já está funcionando legal..... Valeu pela dica...
:lol:

Eu gostaria de saber qual função dos [b:d95e6bfcd5]{$J+}[/b:d95e6bfcd5] e [b:d95e6bfcd5]{$J-} [/b:d95e6bfcd5]?


GOSTEI 0
Michael

Michael

18/06/2004

Que bom que pude ajudar Lucas!


A diretiva de compilação {$J} serve para ativar/desativar o uso de constantes tipadas. A partir do Delphi 6 não é mais possível alterar o valor de uma constante por padrão, apenas utilizar seu conteúdo. Com essas diretivas você ativa esta utilização. Eu utilizei uma constante para manter a variável dentro do procedimento Click da TreeView. Você poderia entretanto criar uma variável global, ou definir um campo do objeto do formulário principal e fazer o mesmo. Para mais informações sobre constantes consulte [url]http://www.clubedelphi.com.br/artigos/Consttip.html[/url]. Se você não colocar essas diretivas no código em questão, o Delphi irá gerar um erro dizendo que você não pode atribuir um valor a uma constante.

Analisando o seu problema, eu percebi duas coisas que devem ser levadas em consideração. Vamos a elas:

1. Utilizar a propriedade Level para definir quais itens são editáveis pode não ser uma maneira prática de localizar tais itens, pois se você futuramente colocá-los um nível abaixo, ou acima, você terá que retornar ao código e alterar o valor de ´Level´ para a nova posição do item. Para contornar isso, você pode fazer o seguinte: O objeto TTreeNode não tem a propriedade Tag, que serviria como uma luva aqui. Porém, existem outras como StateIndex, SelectedIndex e OverlayIndex. A menos que você utilize-as todas em seu aplicativo, você poderia definir um valor de edição, como 1 por exemplo, para alguma delas e assim definir qual ítem é editável. Ficaria muito mais prático lidar com edições na TreeView desta forma,


...

{ Permite a edição apenas se o item selecionado estiver setado para isso}
TreeView1.ReadOnly := not (TreeView1.Selected.OverlayIndex = 1);

...



2. O último código que lhe passei permite apenas a edição automática do ítem quando o usuário clica sobre ele. Porém, se os usuários de seu programa utilizarem o teclado para selecionar os ítens, a edição acontecerá automaticamente. O ideal seria você definir uma tecla de atalho para permitir a alteração do ítem também via teclado. O Windows utiliza a tecla F2 para iniciar o modo de edição dos nomes de arquivos e pastas no Explorer. Talvez fosse uma boa manter este padrão, da mesma forma que o colega 2k sugeriu quanto ao clique sobre o ítem.

Abraços!


GOSTEI 0
Michael

Michael

18/06/2004

pois você poderia definar qualquer ítem para edição, em qualquer nível. Para se utilizar desta abordagem, basta alterar o código anterior para:
GOSTEI 0
Xanatos

Xanatos

18/06/2004

Tambem nao entendi! mas nao deixa de ser interessante!!! 8)

Mas... Se voce fizer dessa maneira tambem funciona!!! colocando o imageindex como tag!!! ou algo assim!

if Node.ImageIndex =1 then
  begin
    TVmenu.Selected.EditText;
  end;


Mude a propriedade ChangeDelay=50 e tambem funciona!! é sempre bom termos alternativas!!!! :arrow:


GOSTEI 0
Michael

Michael

18/06/2004

(...) Porém, se os usuários de seu programa utilizarem o teclado para selecionar os ítens, a edição acontecerá automaticamente. (...)


O correto é que a edição [b:148678b6f3]não[/b:148678b6f3] será permitida. Esqueci do não... :oops:


GOSTEI 0
Vinicius2k

Vinicius2k

18/06/2004

Ao amigo Vinicius2k: meu nome é Michael, e não Michel!
:oops: perdõe-me...
estamos empatados então... meu ´K´ é maiúsculo..

o usuário tem que abrir o node, clicar em cima dele 2 vezes, e ai sim ele abre para edição...

bem... este é o padrão do Windows... creio q para ficar livre dele, teria que usar o código do colega Michael mesmo...

[quote=´Lucas´]Qual é a função dos {$J+} e {$J-}
Código:
{$J+}
const UltimoItemEditado : TTreeNode = nil;
{$J-}

Notei que se não colocar dá um erro de código.[/code]

São diretivas de compilação que ´ligam (+)´ ou ´desligam (-)´ a possibilidade da procedure ou função escrever numa constante... (constantes tipadas)... para que se tenham comportamento semelhante à uma var... creio que o Micheal tenha usado este recurso para permitir a inicialização em conjunto com a declaração, já que uma var não permite isto dentro de procedures ou functions...

T+


GOSTEI 0
Lucas Silva

Lucas Silva

18/06/2004

Obrigado a todos que me ajudaram aqui.
Saiu exatamente do jeito que eu queria...

Michael, estou dando uma lida aqui neste artigo sobre Constantes Tipadas



Até mais pessoal.
Muito Obrigado!
:lol: :lol:


GOSTEI 0
Michael

Michael

18/06/2004

Que coisa hein amigo Vinicius... Ambos erramos os nomes um do outro... ;-)

creio que o Micheal tenha usado este recurso para permitir a inicialização em conjunto com a declaração, já que uma var não permite isto dentro de procedures ou functions...


Na verdade eu usei uma constante tipada para reaproveitar o seu valor em todas as vezes que a procedure for executada. As constantes tipadas, como sabemos, mantêm seu valor durante toda a execução do programa, e por isso as utilizei.

Abraços!


GOSTEI 0
POSTAR