Quero abrir uma tela com um gif enquanto minhas consultas estão rodando. Porém minha tela não aparece, mesmo sendo seu isVisible = true.
Minha aplicação é em Java desktop.
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
public class ThreadLoad extends Thread {
TelaLoad frame;
private volatile boolean fecharFrame = true;
@Override
public void run() {
try {
if (!fecharFrame()) {
frame.setVisible(true);
}
frame.setVisible(false);
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
} catch (Exception e) {
System.out.println("Erro thread: " + e.getMessage());
}
}
public synchronized void requestStop() {
this.fecharFrame = true;
}
public synchronized void requestStar() {
fecharFrame = false;
}
public void frame(TelaLoad j) {
frame = j;
}
public synchronized boolean fecharFrame() {
return fecharFrame;
}
}
-
Utilizo um JDialog onde tenho as funções que utilizo:
public void iniciar() {
//se não tiver thread, abrir uma
if (t.fecharFrame()) {
t = new ThreadLoad();
t.frame(this);
t.requestStar();
t.start();
}
}
public void fechar() {
//se tiver thread, fecha-la
if (!t.fecharFrame()) {
t.frame(this);
t.requestStop();
t.interrupt();
this.dispose();
}
}
Para abrir o load então uso tela.iniciar() e para chega tela.fechar(); Porém mesmo com requisições que demoram a tela com o gif não fica visível.
Alguém poderia me ajudar, obrigado.
Mas você já viu isso funcionando?
Vi exemplos na internet com load que utilizam tempos pré-definidos, porém eu não sei quanto tempo minha consulta dura. Logo, estou tentando fazer algo sem esse tempo, de modo a abrir e fechar um jdialog com a thread
Provavelmente pelo fato de você fechar ela, veja:
if (!fecharFrame()) {
frame.setVisible(true); // abre
}
frame.setVisible(false); // em seguida fecha
Não exemplos na internet, fera. Rodando no teu projeto.
Eu sempre parto do princípio que, ao criar algo, eu faço com que funcione, depois vou ajustando para colocar o mesmo onde é cabível.
Detalhe: (como sempre) o @staroski está corretíssimo.
1 curtida
Não vejo motivo para usar Thread, basta implementar o padrão Observer (ou Listener), aí quando sua consulta termina, você notifica a janela de forma que ela saiba que pode ser fechada.
Eu somente fecho quanto a thread é interrompida. Porém existe um tempo em que a janela deveria aparecer
Se eu não usar thread o foco ficará na tela e a consulta no banco não acontecerá, pois o foco agora é a tela. Pensei em usar thread para rodar duas atividades distintas: mostrar o load e consultar no banco
Sim, estou a bastante dias testando. Roda sim, o que acontece é que debugando o código a tela retorna que está ativa, visível, porém ela não aparece. Este é meu problema
E porque o foco na tela interrompe a sua consulta?
Explica melhor isso aí…
Se instanciarmos uma tela e torná-la ela visível, agora o foco passará a ser dessa tela até que seja fechada. A aplicação só executará o consultar quando a tela for fechada, não é? Isso que aconteceu quando tentei fazer desta forma.
Por exemplo:
TelaLoad load = new TelaLoad(this, true);
t.setVisible(true);
dao.consultarRegistros();
Desculpe caso eu esteja equivocada, só estou tentando entender o funcionamento do que quero! Obrigado.
Começa removendo a linha que irei destacar
Tá, então sua janela é modal, certo? Aí de fato o setVisible vai bloquear a execução.
Pra esse tipo de situação o padrão Observer (também chamado de Listener) vem bem a calhar.
Você pode criar uma interface DaoListener por exemplo, com métodos para notificar o inicio e término da consulta, algo mais ou menos assim:
public interface DaoListener {
// chamado pelo Dao quando a consulta vai iniciar
public void consultaIniciada();
// chamado pelo Dao quando a consulta terminou
public void consultaEncerrada();
}
Aí o método consultarRegistros da sua classe Dao vai receber um objeto DaoListener como parâmetro, assim:
public void consultarRegistros(DaoListener listener) {
listener.consultaIniciada(); // informa o listener de que a consulta vai iniciar
/*
* Aqui vai sua implementação atual que acessa o banco e tudo mais fazendo uma operação demorada...
*/
listener.consultaEncerrada(); // informa o listener de que a consulta terminou
}
Aí sua TelaLoad vai implementar a interface DaoListener, assim:
public class TelaLoad extends ClasseQueTuJaTaEstendendo implements DaoListener {
// método da interface DaoListener
@Override
public void consultaIniciada() {
// executa o setVisible em uma Thread pro método não ficar bloqueado, já que é uma janela modal
new Thread(() -> this.setVisible(true)).start();
}
// método da interface DaoListener
@Override
public void consultaEncerrada() {
this.setVisible(false);
}
}
E o código onde você abre a tela e realiza a consulta, vai ficar assim:
TelaLoad load = new TelaLoad(this, true); // instancia a tela sem chamar o setVisible(true)
dao.consultarRegistros(load); // TelaLoad implementa DaoListener, então passo ela como parâmetro pro Dao

1 curtida
Removi, mas continua a mesma coisa
Opa, obrigado pela orientação. Vou tentar e repasso pra vocês se consegui, agradeço!
1 curtida
Olá, fiz as modificações e aparentemente deu super certo, só tenho um problema: o JDialog (a minha tela com o gif) fica em branco, ela abre e se comporta do jeito adequado porém não carrega os componentes

Infelizmente o GIF não nos mostra como o código foi implementado.
Se o GIF for o problema então nem precisa ser ele, mas pelo menos um JLabel com uma escrita: ‘Carregando’, mas nem isto mostra
Quis dizer que você postou uma imagem no fórum, essa imagem não nos revela como você implementou o código.
Sem ver seu código fonte, não dá pra te indicar onde está o problema. 
Fiz o Listener:
package dao;
public interface DaoListener {
// chamado pelo Dao quando a consulta vai iniciar
public void consultaIniciada();
// chamado pelo Dao quando a consulta terminou
public void consultaEncerrada();
}
Aí em determinado Dao coloquei o codigo pra chamar a tela de load:
public List<Pojo> consultar(DaoListener listener) {
listener.consultaIniciada();
\\codigo da minha consulta
listener.consultaEncerrada();
return list;
}
Aí a tela de load:
` public class LoadTester extends javax.swing.JDialog implements DaoListener {`
/**
* Creates new form LoadTester
*
* @param parent
* @param modal
*/
public LoadTester(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
}
// método da interface DaoListener
@Override
public void consultaIniciada() {
// executa o setVisible em uma Thread pro método não ficar bloqueado, já que é uma janela modal
new Thread(() -> this.setVisible(true)).start();
}
// método da interface DaoListener
@Override
public void consultaEncerrada() {
this.setVisible(false);
}
Estilo da minha tela:

Em resumo segui os passos que me indicou, aí tenho aquele problema que te falei, os componentes da tela não carregam e ela fica em branco no tempo de execução:
