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 só. Nos ifs tem também
//a condição exists, pra saber se o usuário já 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!!!