[static] Não quero usar, como faço?

4 respostas
Vingdel

Olá pessoal,

Tenho a seguinte classe, que é minha classe principal:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class MeuNote extends JFrame{
	//Componentes
	private JToolBar toolbar = new JToolBar("Ferramentas");
	private JMenuBar menubar = new JMenuBar();
	private JMenu arquivo = new JMenu("Arquivo");
	private JTextArea texto = new JTextArea();

	//Ações:
	private Action novo = new NovoAction(this.texto);
	private Action salvar = new SalvarAction(this.texto);
	private Action abrir = new AbrirAction(this.texto);
	
	public void modificarTexto(String str){
		texto.setText(str);
	}

	public MeuNote(){
		super("Meu Notepad");
		//Desliga automaticamente a aplicação quando o usuário fecha a janela.
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container interno = this.getContentPane();
		this.montaMenu();
		this.montaToolBar();
		this.montaGUI(interno);
	}
	private void montaMenu(){
		JMenuItem itemNovo = new JMenuItem(this.novo);
		JMenuItem itemSalvar = new JMenuItem(this.salvar);
		JMenuItem itemAbrir = new JMenuItem(this.abrir);
		this.arquivo.add(itemNovo);
		this.arquivo.add(itemSalvar);
		this.arquivo.add(itemAbrir);
		this.menubar.add(this.arquivo);
		this.setJMenuBar(this.menubar);
	}

	private void montaToolBar(){
		
		this.toolbar.add(this.novo);
		this.toolbar.add(this.salvar);
		this.toolbar.add(this.abrir);
	}

	private void montaGUI(Container interno){
		interno.setLayout(new BorderLayout());
		interno.add(this.toolbar, BorderLayout.NORTH);
		interno.add(new JScrollPane(this.texto));
		setSize(640, 480);
		setLocationRelativeTo(null);
		setVisible(true);
	}

	public static void main(String args[]){
		MeuNote janela = new MeuNote();
	}
}

Tenho também está outra classe, que é a ação do Item "Novo" do meu menu:

//import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
//import javax.swing.event.*;

public class NovoAction extends AbstractAction{
	
	private JTextArea texto = new JTextArea();
	
	public NovoAction(JTextArea texto){
		//Define o nome da ação
		super("Novo");
		//Define mais algumas características
		this.putValue(Action.SMALL_ICON, new ImageIcon("new.gif"));
		this.putValue(Action.SHORT_DESCRIPTION, "Limpa a área de texto");
	}

	//Definimos aqui o procedimento que será executado quando NovoAction for acionado
	public void actionPerformed(ActionEvent ev){
		MeuNote.modificarTexto("aaa");
	}
}

Essa aplicação é um simples editor de texto e quando clico no item "Novo" do meu menu ele seta o texto do meu JTextArea para "aaa" (isso para testar o funcionamento, pois deverá limpar o JTextArea, claro). O problema para o qual busco solução é o seguinte, da forma que está o código, onde a ação do item "Novo" está em:

public void actionPerformed(ActionEvent ev){
	MeuNote.modificarTexto("aaa");
}

O Eclipse me diz que tenho fazer a seguinte mudança na classe principal para funcionar:

private JTextArea texto = new JTextArea();
	// ...
	
	public void modificarTexto(String str){
		texto.setText(str);
	}
para:
private static JTextArea texto = new JTextArea();
	// ...

	public static void modificarTexto(String str){
		texto.setText(str);
	}

Ou seja, setar o JTextArea texto e o método modificarTexto() para static, mas eu não queria setá-los como static.

Como eu devo fazer la na ação do item "Novo" para que não seja necessário setá-los como static?

Desde já agradeço!

Abraço!

4 Respostas

GabrielCardelli

Cara em algum lugar você usa esse metodo dentro de alguma coisa estatica?

ex:
public static void algumMetodo(){

modificarTexto();
}
blackout

Seguinte cara, o eclipse está sugerindo essa modificação pois você está chamando o método direto pela classe dele, ou seja.

//Definimos aqui o procedimento que será executado quando NovoAction for acionado  
public void actionPerformed(ActionEvent ev){  
   MeuNote.modificarTexto("aaa");  // Chamada direta pela classe, sem instancia-la.
}

Para não ter que transformar o método em static, você tem que primeiro instanciar a classe e depois chamar o método, tipo:

//import java.awt.*;  
 import java.awt.event.*;  
 import javax.swing.*;  
 //import javax.swing.event.*;  
   
 public class NovoAction extends AbstractAction{  
       
     private JTextArea texto = new JTextArea(); 
     private MeuNote note = new MeuNote(); //Classe instanciada para chamar seus métodos
       
     public NovoAction(JTextArea texto){  
         //Define o nome da ação  
         super("Novo");  
         //Define mais algumas características  
         this.putValue(Action.SMALL_ICON, new ImageIcon("new.gif"));  
         this.putValue(Action.SHORT_DESCRIPTION, "Limpa a área de texto");  
     }  
   
     //Definimos aqui o procedimento que será executado quando NovoAction for acionado  
     public void actionPerformed(ActionEvent ev){  
         note.modificarTexto("aaa");  //método chamado através da intancia da classe MeuNote.
     }  
 }
Vingdel

Olá pessoal, obrigado pela atenção, mas acho que ainda não está resolvido.

blackout:
Seguinte cara, o eclipse está sugerindo essa modificação pois você está chamando o método direto pela classe dele, ou seja.
//Definimos aqui o procedimento que será executado quando NovoAction for acionado  
public void actionPerformed(ActionEvent ev){  
   MeuNote.modificarTexto("aaa");  // Chamada direta pela classe, sem instancia-la.
}

Para não ter que transformar o método em static, você tem que primeiro instanciar a classe e depois chamar o método, tipo:

//import java.awt.*;  
 import java.awt.event.*;  
 import javax.swing.*;  
 //import javax.swing.event.*;  
   
 public class NovoAction extends AbstractAction{  
       
     private JTextArea texto = new JTextArea(); 
     private MeuNote note = new MeuNote(); //Classe instanciada para chamar seus métodos
       
     public NovoAction(JTextArea texto){  
         //Define o nome da ação  
         super("Novo");  
         //Define mais algumas características  
         this.putValue(Action.SMALL_ICON, new ImageIcon("new.gif"));  
         this.putValue(Action.SHORT_DESCRIPTION, "Limpa a área de texto");  
     }  
   
     //Definimos aqui o procedimento que será executado quando NovoAction for acionado  
     public void actionPerformed(ActionEvent ev){  
         note.modificarTexto("aaa");  //método chamado através da intancia da classe MeuNote.
     }  
 }

blackout, meu camarada, entendo que instanciar a classe é uma solução, também pensei nisso, porém tentei dentro do método NovoAction(JTextArea), acontece que se eu fizer isso cada vez que eu clicar no item "Novo" (que tem como sua ação esta classe que estamos alterando), vai ser instanciada a minha classe principal, ou seja vai abrir uma janela nova em cascata.

O mesmo acontece com a solução que você deu, sendo que está sendo instanciada quando a aplicação roda, e como isso está gerando um loop infinito (caso minha memória RAM fosse infinita, hehehe) resultando em [color=red]Exception in thread "main" java.lang.StackOverflowError[/color], pois contece, Principal, Ação, Principal, Ação e etc... Acredito que seja mais ou menos ese raciocínio, porém com alguma mudança.

Mais uma vez agradeço pela ajuda e aguardo por novas sugestões.

Abração!

[color=red][size=18]EDIT:[/size][/color]

Nas tentativas aqui, acabei por resolver o problema, coisa bem simples por sinal, mas fiquei sem entender porque funciona. Veja:

import java.awt.event.*;
import javax.swing.*;

public class NovoAction extends AbstractAction{
	
	private JTextArea texto = new JTextArea();
	
	public NovoAction(JTextArea texto){
		//Define o nome da ação
		super("Novo");
		//Define mais algumas características
		this.putValue(Action.SMALL_ICON, new ImageIcon("new.gif"));
		this.putValue(Action.SHORT_DESCRIPTION, "Limpa a área de texto");
		this.texto = texto;  // <--- Inseri esta linha
	}

	//Definimos aqui o procedimento que será executado quando NovoAction for acionado
	public void actionPerformed(ActionEvent ev){
		this.texto.setText("aaa");  // <--- Modifiquei esta linha
	}
}

[color=red]Modificações nas linhas[/color] [color=blue]14[/color] [color=red]e[/color] [color=blue]19[/color][color=red].[/color]

Além disso excluí o método modificarTexto() da classe principal MeuNote.

Pois bem, fiz isso, como eu disse, nas tentativas, mas fiquei sem entender porque a modificação acontece na instância JTextArea texto da classe principal se eu seto o texto da instância que está na classe NovoAction.

Explicando até onde entendi:

O que entendi, referente ao texto do TextArea é que a instância que pertence a classe da ação recebe a instância da classe principal e então quando o usuário clica no item "Novo" o método responsável pelo evento seta o texto "aaa" para a instância que está na classe DELE (this). Daí, como o texto foi modificado na instância da classe pricipal, eu não entendi.

Poderiam me iluminar quanto a isso?

Obrigado!

Vingdel

Tenho certeza que alguém sabe me explicar essa dúvida final.

Não deixem essa dúvida passar…

Vlw!

Criado 23 de agosto de 2010
Ultima resposta 24 de ago. de 2010
Respostas 4
Participantes 3