Bug do java ou Bug do Programado...?

9 respostas
brlima

To com esse codigo aqui que tá me dando um banho: Tá exibindo duas vezes a mensagem.

Acho que deveria exibir só uma. Ao menos exibia até a versao 1.4.1, já na 1.4.2_04 tá exibindo 2 vezes.
Alguem pode me dar uma luz?

É o seguinte: O foco entra no Text1. Qdo vc passa pro text2, ele deveria exibir uma mensagem e voltar o foco pro 1.

Codigo:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class FocusTest {
    public static void main(String[] args) {
        JFrame frame  = new JFrame("Focus test");
        final JTextField field1 = new JTextField("Teste1");
        final JTextField field2 = new JTextField("Teste2");
        field1.addFocusListener(new FocusAdapter(){
            public void focusGained(FocusEvent e){}
            public void focusLost(FocusEvent e){
                if( !e.isTemporary() ){
                    System.out.println("ID: " + e.getID());
                    JOptionPane.showMessageDialog(null, "Focus lost in 1");
                    field1.requestFocus();
                }
            }
        });
        frame.getContentPane().add(field1, BorderLayout.WEST);
        frame.getContentPane().add(field2, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setBounds(0,0,200,300);
        frame.show();
        
    }
}

9 Respostas

brlima

Uma ajuda a um rapaz desesperado…!!!..rs :shock:

dsiviotti

Se você tirar o código:

field1.requestFocus();

funciona. A mensagem só aparece uma vez. O porquê é um mistério! :shock:

brlima

“dsiviotti”:
Se você tirar o código:

field1.requestFocus();

funciona. A mensagem só aparece uma vez. O porquê é um mistério! :shock:

Mas é que eu forço o foco continuar no campo 1… nao pode sair… :smiley:

dukejeffrie

Bom… eu acho que vc tem que testar se a origem do evento é o field1…

do javadoc do 1.4:

Acho que os dois recebem FOCUS_GAINED…

boa sorte!
[]s

B

Pessoal, eu também tô com um problema desses. É o seguinte:
Tenho vários DBTextField, e faço uma validação de campo vazio no evento focusLost. O problema é que após o campo perder o foco, ele entra no foco do campo seguinte, que também está vazio, e só depois dispara o evento de validação. Quando ele verifica que o campo que perdeu o foco tá vazio, ele volta o foco para ele, provocando uma outra chamada para o evento de validação do último campo que o foco estava, por isso a mensagem é exibida duas vezes. Se o campo mudasse de foco somente quando fosse validado, isso não aconteceria. No delphi isso funciona assim, o foco só muda de campo, após o evento discarado pela perda do foco ser executado. Dessa forma, podemos garantir que o foco só muda de campo quando o campo for validado. Alguém sabe como fazer isso em Swing?

Bruno Barros.

brlima

Pra resolver esse problema, eu tive que validar o campo quando outro componente ganhasse foco, e nao ao perder o foco.
Foi a unica ideia que tive pra minha situacao.

Flw.

Sami_Koivu

Olá todos,

Hum… se na verdade o que vocês querem é validação, que tal usar o mecanismo do InputVerifier que - pelo que entendo - é para isso mesmo?

Esse exemplo não deixa o usuário sair do campo field1 se está vazio:

package playground;

import javax.swing.*;

import java.awt.*;
public class FocusTest {
    public static void main(String[] args) {
        JFrame frame  = new JFrame("Focus test");
        final JTextField field1 = new JTextField("Teste1");
        final JTextField field2 = new JTextField("Teste2");
        field1.setInputVerifier(new InputVerifier() {

            public boolean verify(JComponent input) {
                JOptionPane.showMessageDialog(null, "Focus lost.. or not quite yet.");
                if(field1.getText().length() == 0 ) {
                    return false;
                } else {
                    return true;
                }
            }
        
        });
        frame.getContentPane().add(field1, BorderLayout.WEST);
        frame.getContentPane().add(field2, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setBounds(0,0,200,300);
        frame.setVisible(true);
        
    }
}

O método verify do seu InputVerifier vai ser chamado quando o usuário tente sair do campo. E se o metodo retornar “false” o componente não perde foco.

Mais informações:
http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/InputVerifier.html

Abraços,
Sami

PS.
[comentário-inútil-e-não-é-pra-levar-sério-demais]
Eu não gosto desse tipo de validação que não me deixa sair do campo. Tenho ataques de raiva quanda minha liberdade fica assim limitado :slight_smile:
Por favor, pense nas foquinhas que escapam o monstruoso Struts e ai ficam presos num campo destes. Triste :slight_smile:
Mas tudo bem, há situações que necessitam isso.
[/comentário-inútil-e-não-é-pra-levar-sério-demais]

brlima

Realmente, esse negocio de prender o foco eu tb nao sou muito fã.

Tive um problema com teu codigo: StackOverFlow ao exibir a mensagem em um JOptionPane.

É normal isso ?

Sami_Koivu

Ah… desculpas. Não é normal, não. Só testei com java1.5 aparentemente. Aí funcionou.

Com 1.4 tenho o mesmo problema.

Abrir o JOptionPane deve gerar outro evento de verify… que cria mais um… etc

Parece ser por causa deste bug aqui:
http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=7cd883a12d3c28aa6acb4bc62f03:YfiG?bug_id=4532517

Então, usando o workaround para 1.4 citado na descrição do bug:

package playground;

import javax.swing.*;

import java.awt.*;
public class FocusTest {
    public static void main(String[] args) {
        JFrame frame  = new JFrame("Focus test");
        final JTextField field1 = new JTextField("Teste1");
        final JTextField field2 = new JTextField("Teste2");
        field1.setInputVerifier(new InputVerifier() {

            public boolean verify(JComponent input) {
                input.setInputVerifier(null);
                JOptionPane.showMessageDialog(null, "Focus lost.. or not quite yet.");
                input.setInputVerifier(this);
                if(field1.getText().length() == 0 ) {
                    return false;
                } else {
                    return true;
                }
            }
        
        });
        frame.getContentPane().add(field1, BorderLayout.WEST);
        frame.getContentPane().add(field2, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setBounds(0,0,200,300);
        frame.setVisible(true);
        
    }
}

Este aqui funcionou até com java 1.4

Abraços,
Sami

Criado 22 de março de 2004
Ultima resposta 3 de ago. de 2005
Respostas 9
Participantes 5