Problema ImageIO [RESOLVIDO]

2 respostas
programaçãojava
T

Oi gente, eu estou com um problemão aqui que não consigo resolver de jeito nenhum.

Bom, eu to usando o ImageIO do Java pra tentar carregar imagens na minha tabela do Javafx, permitindo que eu altere essas imagens. A parte de inserir as imagens e as informações estão dando certo, como podem ver:

Então eu fiz um método no meu Controller pra que quando o usuário clicasse duas vezes num registro da tabela, ele carregasse esse registro em uma outra tela .No caso, a tela Cadastro, que é essa daqui:

(ignorem as imagens desalinhadas)

Então, até aí tudo bem. O meu método de carregamento é esse aqui (Obs: leiam os comentários):

private void carregar() {
        
        //descobre qual o pet selecionado
        Pet selecionado = tabelaPet.getSelectionModel().getSelectedItem();
        if (selecionado == null) {
            return;
        }

        //preenche os TextFields pra edição
        txtNome.setText(selecionado.getNomePet());
        txtNomeDono.setText(selecionado.getDono().getNomeDono());
        this.selecionado = selecionado.getDono();
        txtObs.setText(selecionado.getObservacoes());
        txtRaca.setText(selecionado.getRaca());

        //formata o valor que veio do banco pra bater com o valor que tá no choicebox (espécie é um enum)
        String especieString = selecionado.getEspecie().toString().toLowerCase(),
                primeiroCaracter = new Character(especieString.charAt(0)).toString();

        choiceEspecie.setValue(especieString.replaceFirst(primeiroCaracter, primeiroCaracter.toUpperCase()));
        choicePorte.setValue(selecionado.getPorte());
        choiceSocial.setValue(selecionado.getConvivioSocial());

        //define as duas imagens que vão ser usadas
        Image imagemFoto, imagemCarteirinha;

        try {
            //esses métodos get uri na realidade não tem uri, eles tem uma string em um formato tipo file:/C:/imagensPet/pastaDaFoto/foto.extensão
            fotoPetselecionada = new File(selecionado.getUriFoto());
            imagemFoto = new Image(selecionado.getUriFoto());
        } catch (NullPointerException e) {
            fotoPetselecionada = null;
            imagemFoto = null;
        }
        try {
            cadernetaSelecionada = new File(selecionado.getUriCarteirinha());
            imagemCarteirinha = new Image(selecionado.getUriCarteirinha());
        } catch (NullPointerException e) {
            imagemCarteirinha = null;
            cadernetaSelecionada = null;
        }

        //o imageCarteirinha e o imageFoto são dois imageViews
        imageCarteirinha.setImage(imagemCarteirinha);
        imageFoto.setImage(imagemFoto);
        //aqui que tá o pulo do gato. Pra diferenciar as inserções das edições dos Pets, eu criei
        //um campo chamado carregado (que é um Pet). quando esse carregado está nulo, o programa faz inserção
        //e quando ele está preenchido, o programa faz edição. Vou explicar mais disso no próximo método
        carregado = selecionado;
        //aqui é mudada a tela
        tabPane.getSelectionModel().select(tabCadastro);
        //essa é uma mensagem que sobe no canto da tela só
        MensagensNotificacao.mostrarSucesso("Pet carregado");

    }

O carregamento acontece normalmente, mas o problema está quando o usuário clica no botão confirmar, pois então é disparado um método chamado cadastrar. Leiam os comentários novamente:

private void cadastrar() {

        //O método controiPet retorna uma nova instancia de Pet. Vou indexar ele em baixo
        //desse método cadastrar
        Pet novo = constroiPet();
        //se der algum erro de validação no método constroiPet, ele retorna null, e então a operação é abortada
        if (novo == null) {
            return;
        }
        
        //Estamos chegando perto da raiz do problema! O método salvar imagem usa o ImageIO pra ler as imagens postas
        //em dois campos do tipo File: fotoPetSelecionada e cadernetaSelecionada. No caso, eu estou gerando dois arquivos,
        //um pra cada if. Vou indexar esse método comentado também. 
        //Obs: esses File.separator são uma barra . Nos ifs tem também 
        //a condição exists, pra saber se o usuário  não cadastrou aquela foto, não precisando assim gerar um novo arquivo
        
        if (novo.getUriFoto() != null && !new File(novo.getUriFoto()).exists()) {
            salvarImagem(fotoPetselecionada, "C:" + File.separator + "imagensPet" + File.separator + "imagensPerfil" + File.separator);
        }
        if (novo.getUriCarteirinha() != null && !new File(novo.getUriCarteirinha()).exists()) {
            salvarImagem(cadernetaSelecionada, "C:" + File.separator + "imagensPet" + File.separator + "imagensCadernetas" + File.separator);
        }

        try {
            //Aqui que é aplicado aquilo que eu disse do carregado,
            //que para nulo é inserção e preenchido edição. Quando o usuário clica duas vezes
            //num registro da tabela, é realizada uma edição
            if (carregado != null) {

                //sets
 
                carregado.setConvivioSocial(novo.getConvivioSocial());
                carregado.setDono(novo.getDono());
                carregado.setEspecie(novo.getEspecie());
                carregado.setNomePet(novo.getNomePet());
                carregado.setObservacoes(novo.getObservacoes());
                carregado.setPorte(novo.getPorte());
                carregado.setRaca(novo.getRaca());
                carregado.setUriCarteirinha(novo.getUriCarteirinha());
                carregado.setUriFoto(novo.getUriFoto());

                //Aqui é realizado um merge via JPA na base de dados (essa parte está funcionando perfeitamente)
                petDAO.alterar(carregado);
            } else {
                //Aqui é para o caso de inserção (carregado nulo)
                petDAO.inserir(novo);
                MensagensNotificacao.mostrarSucesso("Pet de nome " + novo.getNomePet() + " cadastrado com sucesso!");
            }
            //esse método limpa os TextFields e deixa os campos nulos (aqueles Files e o carregado são esses campos)
            limpar();
            //esse método tira todos os itens da tabela e em seguida preenche ela com os valores do banco
            atualizaTabela();
        } catch (Exception e) {
            FxDialogs.showException("", "", e);
            MensagensNotificacao.mostrarErro("Erro ao cadastrar o Pet!");
        }

    }

Método salvarImagem (onde ocorre a exceção)

private void salvarImagem(File fotoPetselecionada, String caminho) {
        //Aqui é o pulo do gato de vez. Vou explicar os parâmetros:
        //o primeiro é o arquivo que vai ser cadastrado. Como eu disse
        //antes, são as imagens que são carregadas por um FileChooser.
        if (fotoPetselecionada == null) {
            MensagensNotificacao.mostrarErro("Nenhuma foto selecionada para o Pet.");
            return;
        }
        try {
            //Aqui é assim: peguei uma classe na internet (essa FxDialogs)
            //pra poder receber as mensagens tipo um sysout. O mais estranho é:
            //pra algumas imagens...
            FxDialogs.showInformation("", fotoPetselecionada.toURI().toURL().toString());//<---- esse fotoPetselecionada.toURI().toURL().toString()...
            //mostra um formato de arquivo e pra outras ele mostra outro formato.
            
            //Vou deixar duas imagens com os dois formatos pra vocês tentarem entender o que está acontecendo
            
            //aqui é gerada a exceção javax.imageio.IIOException: Can't read input file!
            BufferedImage img = ImageIO.read(fotoPetselecionada);
            
            //Aqui eu pego a extensão do arquivo pra usar no write (é um dos parâmetros)
            String formato = fotoPetselecionada.getName().substring(
                    fotoPetselecionada.getName().lastIndexOf(".") + 1, fotoPetselecionada.getName().length());

            //aqui eu garanto que as pastas estão criadas
            File path = new File(caminho);
            path.mkdirs();

            //aqui é gerado o arquivo (era pra ser)
            ImageIO.write(img, formato, new File(caminho + fotoPetselecionada.getName()));

        } catch (IOException ex) {
            FxDialogs.showException("", "", ex);
            MensagensNotificacao.mostrarErro("Erro ao salvar a imagem!");
        }

    }

Vou deixar o método constroiPet aqui caso ajude:

private Pet constroiPet() {
        if (selecionado == null) {
            MensagensNotificacao.mostrarErro("Selecione um tutor para cadastrar o Pet.");
            return null;
        }

        //Declarando as variáveis
        String nomePet = txtNome.getText(), porte = choicePorte.getValue(), convivioSocial = choiceSocial.getValue(),
                raca = txtRaca.getText(), uriCarteirinha = null,
                observacoes = txtObs.getText(),
                uriFoto = null, especieString = choiceEspecie.getValue();

        //verificando se as URLs das fotos são válidas
        if (fotoPetselecionada != null) {
            try {
                uriFoto = new File("C:" + File.separator + "imagensPet/imagensPerfil/" + fotoPetselecionada.getName()).toURI().toURL().toExternalForm();
            } catch (MalformedURLException ex) {
                MensagensNotificacao.mostrarErro("Caminho especificado para a foto do Pet é inválidos.");
            }
        }

        if (cadernetaSelecionada != null) {
            try {
                uriCarteirinha = new File("C:/i"
                        + "magensPet/imagensCadernetas/" + cadernetaSelecionada.getName()).toURI().toURL().toExternalForm();
            } catch (MalformedURLException ex) {
                MensagensNotificacao.mostrarErro("Caminho especificado para a foto da caderneta de vacinação é inválido.");
            }
        }

        //verificando se algum dos campos está vazio
        if (raca == null) {
            raca = "Nenhuma Especificada";
        }
        if (nomePet == null) {
            MensagensNotificacao.mostrarErro("Informe o nome do Pet a ser cadastrado.");
            return null;
        }

        //transformando espécie string em enum
        Especie especie = Especie.OUTRO;
        if (especieString.equals("Gato")) {
            especie = Especie.GATO;
        } else if (especieString.equals("Cão")) {
            especie = Especie.CÃO;
        }

        return new Pet(selecionado, nomePet, porte, convivioSocial, raca, especie, uriCarteirinha, observacoes, uriFoto);
    }

Vou fazer um passo a passo do que acontece em imagens:

1-) Abre o menu de Pets

2-) Clica duas vezes e seleciona um pet

3-) Mudando as fotos

4-)Caminho da primeira imagem:

5-) Caminho da segunda imagem:

6-) Até aí tudo bem, porque eu mudei as duas imagens. Agora vou mudar uma só:

7-) Aqui está aquele formato estranho da URL, que tem dois file:/ (em nenhum momento isso é especificado por mim)!

Exceção gigantesca gerada:

javax.imageio.IIOException: Can't read input file!
	at javax.imageio.ImageIO.read(ImageIO.java:1301)
	at trickstival.CadastroPetsController.salvarImagem(CadastroPetsController.java:404)
	at trickstival.CadastroPetsController.cadastrar(CadastroPetsController.java:284)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
	at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Node.fireEvent(Node.java:8411)
	at javafx.scene.control.Button.fire(Button.java:185)
	at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
	at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
	at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
	at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
	at javafx.event.Event.fireEvent(Event.java:198)
	at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
	at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
	at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$355(GlassViewEventHandler.java:388)
	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
	at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
	at com.sun.glass.ui.View.notifyMouse(View.java:937)
	at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
	at java.lang.Thread.run(Thread.java:745)

Resultado ao carregar o mesmo Pet novamente:

A foto sumiu!!!

Olhando no banco:

A imagem continua!
Mas mesmo reiniciando a aplicação, a imagem não é carregada.

Por favor me ajudem!!!

2 Respostas

D

No método carregar, já carrega a imagem do tipo Image do JavaFx, onde está:

imagemFoto = new Image(selecionado.getUriFoto());

então altere o salvarImagem para receber imagemFoto como parâmetro:

private void salvarImagem(Image imagemFoto, String caminho) {

e insira o código:

File outputFile = new File(caminho);
BufferedImage bImage = SwingFXUtils.fromFXImage(imagemFoto, null);
try {
  ImageIO.write(bImage, "png", outputFile);
} catch (IOException e) {
  throw new RuntimeException(e);
}

http://www.java2s.com/Tutorials/Java/JavaFX_How_to/Image/Save_an_Image_to_a_file.htm

T

Diego muito obrigado cara!!! PQP, você não faz ideia do como eu quebrei a cabeça e você me dá a solução assim na tranquilidade. Muito obrigado mesmo, está funcionando perfeitamente. Fico feliz que ainda existam pessoas boas como você, Abraço!

Criado 15 de janeiro de 2017
Ultima resposta 15 de jan. de 2017
Respostas 2
Participantes 2