Duvida Acao ao clickar Java Error Voltar

Ola, eu estou tendoum problema que quando vou executar este programa nao esta executando, Eu nao sei o porque, aconteceu isso quando tentei adicionar o voltar nas Classes que precisam voltar a TCaixa.

Classe TCaixa

package Trab;

import java.awt.Container;  
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;  
import javax.swing.JFrame;  
import javax.swing.JLabel;  
import javax.swing.JOptionPane; 

public class TCaixa extends JFrame{  

    JButton cancelar = new JButton("Cancelar");  
    JButton ok = new JButton("ok");
    
    JButton saque = new JButton("Saque");  
    JButton extrato = new JButton("Extrato");
    JButton depositar = new JButton("Depositar");
    JButton transferir = new JButton("Transferir");
    

    public TCaixa (){  


        super("Caixa");  

        Container c = getContentPane();

        c.setLayout(new GridLayout(3,2));
        
        saque.addActionListener(new ActionListener() {
        	TSacar telaS = new TSacar();
			public void actionPerformed(ActionEvent s){
		     telaS.setVisible(true);
		     dispose();
			}
        });
        c.add(saque);
        
        extrato.addActionListener(new ActionListener() {
        	TExtrato telaE = new TExtrato();
			public void actionPerformed(ActionEvent a){
		     telaE.setVisible(true);
		     dispose();
			}
        });
        c.add(extrato);
        
        depositar.addActionListener(new ActionListener() {
        	TDepositar telaD = new TDepositar();
			public void actionPerformed(ActionEvent d){
		     telaD.setVisible(true);
		     dispose();
			}
        });
        c.add(depositar);
        
        transferir.addActionListener(new ActionListener() {
        	TTransferir telaT = new TTransferir();
			public void actionPerformed(ActionEvent t){
		     telaT.setVisible(true);
		     dispose();
			}
        });
        c.add(transferir);

        ok.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e){
		     setVisible(true);
		     dispose();
			}
        });
        c.add(ok);
        c.add(cancelar);



        setSize(300,200);
        setDefaultCloseOperation(EXIT_ON_CLOSE);


    }
    public static void main(String[] args) {
    Telainicial chamatela = new Telainicial();
    chamatela.setVisible(true);
    }
}

Uma das classes que tem a opcao de voltar (Classe TSacar)

package Trab;

import java.awt.Container;  
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;  
import javax.swing.JFrame;  
import javax.swing.JLabel;  
import javax.swing.JOptionPane;   
import javax.swing.JTextField;  

public class TSacar extends JFrame{  

    JButton voltar = new JButton("Voltar");  
    JButton ok = new JButton("ok");
    
    JTextField saque = new JTextField();
    
    TCaixa tela = new TCaixa();

    public TSacar (){


        super("Saque");  

        Container c = getContentPane(); 

        c.setLayout(new GridLayout(3,2));  
        c.add(new JLabel ("Quanto deseja sacar:"));  
        c.add(saque);  

        ok.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e){
		     tela.setVisible(true);
		     dispose();
			}
        });
        c.add(ok);
        
        voltar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e){
		     tela.setVisible(true);
		     dispose();
			}
        });
        c.add(voltar);



        setSize(300,200);
        setDefaultCloseOperation(EXIT_ON_CLOSE);


    }

}

O Erro que esta dando e este aqui:

Exception in thread “main” java.lang.StackOverflowError
at sun.awt.Win32GraphicsConfig.getBounds(Native Method)
at sun.awt.Win32GraphicsConfig.getBounds(Unknown Source)
at java.awt.Window.init(Unknown Source)
at java.awt.Window.(Unknown Source)
at java.awt.Frame.(Unknown Source)
at javax.swing.JFrame.(Unknown Source)
at Trab.TCaixa.(TCaixa.java:27)
at Trab.TSacar.(TSacar.java:21)
at Trab.TCaixa$1.(TCaixa.java:34)
at Trab.TCaixa.(TCaixa.java:33)
… e repete…

Se alguem ajudar, agredeco :slight_smile:

Como sou Iniciante em Java nao sei direito identificar os erros, se alguem puder dar uma ajudinha.

No construtor da classe TCaixa você está instanciando a classe TSacar, que em seu construtor cria uma nova instância de TCaixa, que em seu construtor cria uma nova instância de TSacar, que em seu construtor cria uma nova instância de TCaixa, que em seu construtor cria uma nova instância de TSacar, que em seu construtor cria uma nova instância de TCaixa, que em seu construtor cria uma nova instância de TSacar, que em seu construtor cria uma nova instância de TCaixa, que em seu construtor cria uma nova instância de TSacar, que em seu construtor cria uma nova instância de TCaixa, que em seu construtor cria uma nova instância de TSacar, que em seu construtor cria uma nova instância de TCaixa, que em seu construtor cria uma nova instância de TSacar, que em seu construtor cria uma nova instância de TCaixa, que em seu construtor cria uma nova instância de TSacar, que em seu construtor cria uma nova instância de TCaixa, que em seu construtor cria uma nova instância de TSacar, que em seu construtor cria uma nova instância de TCaixa

Aí chega um momento que não há mais pilha de memória pra fazer isso, entendeu?

Entendi, So que eu queria fazer com que a acao voltasse a tela TCaixa, como eu faco para acontecer isso então?

Consegui Vlw :slight_smile:

Como você fez, criou uma classe controladora para suas telas ou você passa uma como parâmetro para a outra?

EU apenas tirei os TSacar telaS = new TSacar(); de cada um e mudei usando apenas o .show();
E ficou assim

saque.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent s){
	     new TSacar().show();
	     dispose();
		}
    });

So que agora uma duvida que estou e que nao sei como pegar os valores digitados na Classe TDepositar e por uma condicao na classe TSacar para que o usuario faca o saque.

Tenha em mente que a instrução new tem esse nome justamente pelo fato de ela alocar espaço em memória e instanciar um novo objeto.
Então no seu exemplo você não está voltando, você está sempre criando uma nova tela do mesmo tipo que a anterior.

Outra coisa, em princípio, somente uma classe deveria ter o método main, vi que hoje você tem um main na classe TCaixa e você tem uma classe chamada TelaInicial, em principio o main deveria ficar só na TelaInicial, ou melhor ainda, em uma classe que represente o ponto de entrada do seu sistema, por exemplo uma classe MeuSistema.

Sobre as suas instanciações de telas, vou te dar uma dica, que vai facilitar sua vida, crie uma classe Telas, que será responsável por instanciar e manter as instâncias das suas telas, aí, em todo lugar onde hoje você faz new TelaQueDeseja(), você vai substituir por uma chamada a um método da classe Telas.
Você também não vai mais fazer o dispose, das suas telas, ao invés disso, faça setVisible(false).

Classe Telas:

public final class Telas {

	private static final Telas instance = new Telas();

	public static Telas get() {
		return instance;
	}

	private TCaixa caixa;
	private TDepositar depositar;
	private Telainicial telaInicial;
	private TExtrato extrato;
	private TSacar sacar;
	private TTransferir transferir;

	private Telas() {}

	public synchronized TCaixa caixa() {
		if (caixa == null) {
			caixa = new TCaixa();
		}
		return caixa;
	}

	public synchronized TDepositar depositar() {
		if (depositar == null) {
			depositar = new TDepositar();
		}
		return depositar;
	}

	public synchronized TExtrato extrato() {
		if (extrato == null) {
			extrato = new TExtrato();
		}
		return extrato;
	}

	public synchronized TSacar sacar() {
		if (sacar == null) {
			sacar = new TSacar();
		}
		return sacar;
	}

	public synchronized Telainicial telaInicial() {
		if (telaInicial == null) {
			telaInicial = new Telainicial();
		}
		return telaInicial;
	}

	public synchronized TTransferir transferir() {
		if (transferir == null) {
			transferir = new TTransferir();
		}
		return transferir;
	}
}

Agora veja como você vai alterar sua tela TCaixa:

import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class TCaixa extends JFrame {

	JButton cancelar = new JButton("Cancelar");
	JButton ok = new JButton("ok");

	JButton saque = new JButton("Saque");
	JButton extrato = new JButton("Extrato");
	JButton depositar = new JButton("Depositar");
	JButton transferir = new JButton("Transferir");

	public TCaixa() {

		super("Caixa");

		Container c = getContentPane();

		c.setLayout(new GridLayout(3, 2));

		saque.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent s) {
				Telas.get().sacar().setVisible(true);
				setVisible(false);
			}
		});
		c.add(saque);

		extrato.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent a) {
				Telas.get().extrato().setVisible(true);
				setVisible(false);
			}
		});
		c.add(extrato);

		depositar.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent d) {
				Telas.get().depositar().setVisible(true);
				setVisible(false);
			}
		});
		c.add(depositar);

		transferir.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent t) {
				Telas.get().transferir().setVisible(true);
				setVisible(false);
			}
		});
		c.add(transferir);

		ok.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				setVisible(false);
			}
		});
		c.add(ok);
		c.add(cancelar);

		setSize(300, 200);
		setDefaultCloseOperation(EXIT_ON_CLOSE);

	}

	public static void main(String[] args) {
		Telas.get().telaInicial().setVisible(true);
	}
}

E a classe TSacar:

import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

public class TSacar extends JFrame {

	JButton voltar = new JButton("Voltar");
	JButton ok = new JButton("ok");

	JTextField saque = new JTextField();

	public TSacar() {

		super("Saque");

		Container c = getContentPane();

		c.setLayout(new GridLayout(3, 2));
		c.add(new JLabel("Quanto deseja sacar:"));
		c.add(saque);

		ok.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Telas.get().caixa().setVisible(true);
				setVisible(false);
			}
		});
		c.add(ok);

		voltar.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Telas.get().caixa().setVisible(true);
				setVisible(false);
			}
		});
		c.add(voltar);

		setSize(300, 200);
		setDefaultCloseOperation(EXIT_ON_CLOSE);

	}
}

Faça essas alterações em todas as suas classes que abrem telas, onde houver um new ClasseDaTela(), você vai substituir por Telas.get().classeDaTela().

Staroski, boa tarde, desculpe estar revivendo o tópico. Você me indicou essa solução pois estava com o mesmo problema na questão de acessar valor de variáveis que pertencem a outro Jframe, Mudei minha aplicação criando uma classe para gerenciar as telas do jeito que você falou, e realmente é muito melhor, porém me deparo com outra situação.

  • Eu tenho no topo do meu programa uma pequena implementação para alterar o Look And Feel, onde eu salvo no banco para manter o look And Feel quando o usuário abrir o programa novamente, só que se alguma das telas for aberta e depois o look and feel for trocado essa tela fica com o look and feel antigo, existe uma forma de reiniciar a aplicação quando trocar o look and feel? como posso resolver esse problema, sou iniciante e estou buscando esse conhecimento, novamente obrigado, estou aprendendo muito com você.