Estou utilizando o GlassPane para interceptar eventos Mouse e MouseMotion e depois dispará-los para um componente específico existente no LayeredPane. Utilizei como base a seção RootPane do Tutorial Java da Sun (http://java.sun.com/docs/books/tutorial/uiswing/components/rootpane.html) para construir meu código.
Funciona mais ou menos assim, quando eu clico no GlassPane, eu verifico qual componente está neste rumo (no layered pane), e disparo o click ele.
De inicio parecia tudo funcionar bem, mas depois percebi que alguns eventos não funcionam. O clique funciona bem, o released também, mas o mouseExited por exemplo não funciona, afinal, o evento é inicialmente disparado quando eu saio com o mouse do GlassPane, neste caso, nenhum componente estará neste rumo para receber o evento. Eu preciso saber se o mouse saiu do rumo de um componente do LayeredPane, ou se entrou (mouseEntered), etc…
No meu caso, existem vários painéis sobrepostos no layered pane, então eu primeiro identifico quem está por cima, e disparo o evento para este painel. O painel por sua vez, encontra o componente que está na posição x e y do evento (acho que aqui que entra o problema) utilizando SwingUtilities.getDeepestComponentAt(), e em seguida dispara o evento para este componente.
Alguem tem alguma luz para me ajudar a solucionar este problema?
Tem uma coisa que eu não entendi. Se você repassa os eventos do glasspane para os componentes embaixo dele, e quer que funcione como se não tivesse nenhum glasspane ali, para que você tem um glasspane?
Deixa eu explicar melhor então…
Eu tenho diversos painéis em um LayeredPane que podem ou não estar sobrepostos.
Cada painel tem seus componentes (botões, textfields, spinners, etc).
Todos os painéis estão transparentes (setOpaque(false)).
Com isso, eu consigo ver botões de um painel que está por trás de outro painel, mas se eu tentar clicar nele, o painel que está por cima não deixará o evento ser acionado no componente (o botão) que está atrás… Para solucionar isto, eu verifico se o clique foi feito em uma parte transparente do painel, caso seja, eu disparo o evento para outro painel permitindo que o evento funcione no componente que eu tentei clicar (que estava em um painel mais atrás). Recentemente eu coloquei os ouvintes no GlassPane para controlar tudo de um lugar só, antes os ouvintes ficavam em um PainelPrincipal que tinha exatamente essa função do glass, pois eu não conhecia a funcionalidade do glass ainda, mas funcionava da mesma forma (não funcionava né?). O que eu preciso é disparar os eventos todos para os componentes específicos, atualmente alguns eventos como mousePressed, mouseReleased e mouseDragged funcionam, mas eu queria que todos os eventos de mouse funcionassem.
Ficou mais claro? To fazendo besteira? Tem alguma maneira mais fácil de fazer?
Já que foi o ViniGodoy que perguntou, esta solução está sendo implementada em um sistema de menus que fiz para um RPG Online que estou desenvolvendo em java. O jogo permite que sejam abertos vários menus sobrepostos, o que me causa este problema que estou tentando corrigir. Alguns me diriam pra fazer de maneira mais simples, tirar a transparência sei lá, mas eu não sou de desistir de uma idéia, deve haver uma maneira de fazer e eu quero descobri-la.
Eu só disparo o evento para o componente se ele estiver na posição X e Y do evento. Mas isto é um erro, afinal, é normal o evento mostrar posições X e Y negativas, isto é, o evento deve ser disparado independente de estar sobre um componente, permitindo assim que o componente possa identificar o mouseEntered e mouseExited. Claro que eu devo converter a posição X e Y do glassPane para o componente, mas isto o SwingUtilities.convertPoint() resolve pra mim.
Mas eu não posso disparar todos os eventos para todos os componentes que eu tenho, pois se dois componentes estiverem em um mesmo rumo do LayeredPane, um clique pode acionar a ação dos dois componentes, sendo que a intenção é que acione apenas do componente que estiver por cima. Para resolver isto, eu penso em primeiro identificar o painel que está por cima (já estava assim), para só então disparar o evento para todos os componentes deste painel.
Como pegar todos os componentes (e sub-componentes) de um painel? Ao usar o getComponents() ele me retorna só os componentes diretamente adicionados neste painel, como eu uso paineis pra organizar o layout, ele só me retorna estes paineis, que por sua vez podem ter outros paineis dentro, etc… Para pegar todos os componentes terei que fazer uma recursividade??
Realmente não é difícil, mas eu resolvi testar a idéia de enviar o evento independente da posição X e Y dele, para os componentes antes de implementar o código todo. O que aconteceu é que o componente recebe o evento mouseMoved independente da posição do mouse estar sobre ele, mas ele não consegue realizar o mouseEntered e mouseExited. O evento já vai com o tipo dele. Quando eu retiro o mouse do GlassPane ele dispara o mouseExited para o componente, o que não é correto…
Resumindo, a idéia não funcionou… O envio do evento para o componente, independente da posição do mouse, não está errada, é normal receber posições negativas ou maiores que a área do componente, mas isto não resolveu o meu problema.
Os únicos eventos que não estão funcionando são mouseEntered e mouseExited. Estou tentando evitar de fazer um tratamento na mão para saber se o ponteiro do mouse entrou ou saiu do rumo de um componente…
A minha idéia agora está em tentar trabalhar com o Toolkit adicionando um AWTEventListener, verificando se o evento foi do tipo MouseListener ou MouseMotionListener, dispará-lo ao painel para ver se o Toolkit do painel trata o evento identificando em relação ao painel que tipo de evento foi (clicked, entered, exited, etc…).
Só que eu não sei nada sobre isso, to começando a pesquisar agora, talvez eu esteja falando besteira.