Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

kapak

TComboBox e Duplicates

Recommended Posts

Olá colegas, como fazer para não inserir ítens duplicados num ComboBox.Num TStringList qdo se ativa a propriedade Sorted e deixa a propriedade Duplicates = Dupignore, ele não insere ítens duplicados.O TComboBox.Items descende de TStrings e não possui a propriedade Duplicates.Já tentei castear TStringList(TComboBox.Items).Duplicates = Dupignore, mas mesmo assim ele insere ítens em duplicidade; então atualmente utilizo um TStringList e depois assinalo TComboBox.Items p/ o TStringList.Alguém saberia como fazer isto diretamente no ComboBox ?Abraços !!!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Colega, veja:

Var wItem : String;Begin    wItem := 'Item01';    If ComboBox1.Items.IndexOf( wItem ) >= 0 Then        ShowMessage( 'Já existe!' )    Else        ComboBox1.Items.Add( wItem );End;

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá, obrigado pela resposta. Olha, sem querer criticar, mas confesso que apanhei um pouco com isso e a minha primeira solução foi o IndexOf. você pode fazer um teste, e verá que a performance cai muitíssimo em relação ao TStringList e depois o Assign.

Compartilhar este post


Link para o post
Compartilhar em outros sites

[...] verá que a performance cai muitíssimo em relação ao TStringList e depois o Assign.

Você tem razão.

 

TStrings.IndexOf é uma rotina lenta: ela faz busca linear na lista de strings e, por causa disso, no caso da string não estar duplicada (o que provavelmente acontece na maior parte das vezes), ela percorre toda a lista a cada inserção.

 

Por outro lado, num TStringList ordenado, TStringList.Add usa busca binária, o que faz a busca por strings duplicadas ser extremamente rápida. Note que a busca binária é utilizada apenas se a lista for ordenada.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Realmente a caixa de combinação do Windows foi idiotamente projetada. Você terá que fazer isto por si mesmo.

 

Mantenha uma TStringList, L, que tem o código necessário para a checagem.

 

procedure TForm1.Button1Click(Sender: TObject);var  S: String;begin  S := Edit1.Text;  ComboBox1.Items.Insert(L.Add(S), S);end;procedure TForm1.FormCreate(Sender: TObject);begin  L := TStringList.Create;  L.Sorted := True;  L.Duplicates := dupError;end;

O problema, como esta solução simples é que há duas listas que contém exatamente a mesma coisa. Enquanto a caixa combo não permite ítems virtuais, a StringList gerencia sua própria lista interna apenas.

 

Se você deseja evitar as cópias em run-time, ou reimplemente busca binária e inserção na caixa combo(como é feito na TStringList em Classes.pas), ou use uma lista owner draw, que pinta a partir da lista L. A primeira opção dá mais trabalho, mas seria mais eficiente, porque a cambo ainda mantém uma lista interna(não é virtual).

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Beppe, bom atualmente faço o seguinte:1-Crio um TStringList c/ Sorted, not CaseSensitive e Duplicates=DupIgnore.2-Vou adicionando tudo lá em run-time.3-No término das adiçoes executo: TComboBox.Items.Assign(TStringList).4-Libero a TStringList.Com isto obtive uma performance bem superior à do IndexOf do combo.Pode não ser o método ideal, mas a performance agora é satisfatória.Só que ficou uma dúvida:Pq quando eu libero a TStringList, não afeta nos ítens da combo?Eu não estaria liberando a mesma área de memória da TComboBox.Items ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que o Assign realoca outra área de memória e faz uma cópia dos dados originais.Será isto ?  :huh:

Exatamente. Tanto a lista em TStringList bem como da combo são listas internas, cada uma com sua cópia.A maneira que está fazendo atualmente com certeza deve ser a melhor para o seu caso, já que você não parece precisar manter as duas listas ao mesmo tempo. Há um custo para a copia que Assign faz, mas dificilmente será significativo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Deve haver uma maneira de "dizer" ao ComboBox que o Items dele será a TStringList L, não?[]'s,

Não, pq se o programador tivesse acesso a lista interna, que provavelmente não contém apenas strings, da combo(pq teria acesso, se a lista pudesse ser Assign'ada), ele poderia desestabilizar o sistema, pq os elementos gráficos rodam no kernel.Talvez haja uma maneira de manter os item ordenados dentro da combo mesmo, mas o Delphi não exporta esta facilidade. Mesmo que haja, precisaria deste suporte em todos os Windows, e os mais antigos, 95 e 98 não devem ter.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.