Como posso usar os ouvintes para acessar outros elementos?
-
03-07-2019 - |
Pergunta
Estou configurando uma GUI onde preciso obter informações inseridas dos elementos de formulário e manipular as informações. Isso exige que eu use alguns elementos para acessar outros.
Por exemplo, eu tenho uma caixa de entrada (JTextField
) e um botão (JButton
) ao lado dele. Quando o botão é pressionado, preciso manipular o texto inserido na caixa de entrada. Tudo o que tentei fazer até agora para fazer isso falhou.
É assim que meu código parece agora (incorporei minhas perguntas nos comentários):
public class MyClass
{
public static void main(String args[])
{
// Form elements are in here
JTextField myTextField = new JTextField(10);
JButton myTextFieldSubmit = new JButton("Submit");
myTextFieldSubmit.addActionListener(new ListenerClass());
}
}
class ListenerClass implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// This is what happens when these elements are used
// I need to be able to access the form elements from MyClass in here, but this doesn't seem possible with my current setup
// For example, when the Submit button is pressed, I need to be able to myTextField.getText() and edit MyClass members
// How should my setup be changed to accommodate these needs?
}
}
Obrigado por qualquer ajuda!
Solução
Esse é um problema de escopo variável.
Atualmente, o campo de texto e o botão estão no escopo do main
método, portanto, ter uma classe separada para o ActionListener
significará que não terá acesso a essas variáveis.
Existem algumas maneiras de conseguir isso:
(1) Faça uma classe interna ListenerClass
dentro MyClass
, e girar o myTextField
e myTextFieldSubmit
em campos de instância de MyClass
.
public class MyClass
{
final static JTextField myTextField = new JTextField(10);
final static JButton myTextFieldSubmit = new JButton("Submit");
public static void main(String args[])
{
myTextFieldSubmit.addActionListener(new ListenerClass());
}
static class ListenerClass implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
myTextField.setText("");
}
}
}
(2) fazer uma classe interna anônima na main
método, e isso permitirá myTextField
e myTextFieldSubmit
permanecer no mesmo lugar, desde que sejam declarados final
.
public class MyClass
{
public static void main(String args[])
{
final JTextField myTextField = new JTextField(10);
final JButton myTextFieldSubmit = new JButton("Submit");
myTextFieldSubmit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
myTextField.setText("");
}
});
}
}
(3) Faça uma classe local que seja local para o main
método. Novamente, isso exigirá que o campo de texto e o botão sejam declarados final
Para permitir o acesso da classe interna.
public class MyClass
{
public static void main(String args[])
{
final JTextField myTextField = new JTextField(10);
final JButton myTextFieldSubmit = new JButton("Submit");
class ListenerClass implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
myTextField.setText("");
}
}
myTextFieldSubmit.addActionListener(new ListenerClass());
}
}
(4) entregando uma referência ao ListenerClass
, por exemplo, no construtor, e também fazendo myTextField
e myTextFieldSubmit
uma variável de instância.
public class MyClass
{
JTextField myTextField = new JTextField(10);
JButton myTextFieldSubmit = new JButton("Submit");
public MyClass()
{
myTextFieldSubmit.addActionListener(new ListenerClass(this));
}
public static void main(String args[])
{
new MyClass();
}
}
class ListenerClass implements ActionListener
{
MyClass myClass;
public ListenerClass(MyClass myClass)
{
this.myClass = myClass;
}
public void actionPerformed(ActionEvent e)
{
myClass.myTextField.setText("");
}
}
(5) fazer myTextField
e myTextFieldSubmit
em static
campos e permitir acesso direto do ListerClass
.
public class MyClass
{
static JTextField myTextField = new JTextField(10);
static JButton myTextFieldSubmit = new JButton("Submit");
public static void main(String args[])
{
myTextFieldSubmit.addActionListener(new ListenerClass());
}
}
class ListenerClass implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
MyClass.myTextField.setText("");
}
}
Provavelmente ainda existem mais maneiras de conseguir isso, e pode haver melhores maneiras de implementar isso. A escolha de qual abordagem você adota realmente depende do design desejado do aplicativo.
Outras dicas
Você pode passar em uma referência a MyClass
no construtor para ListenerClass
.
Seu problema é comum ao uso de ouvintes para qualquer finalidade em Java: como deixar o manipulador acessar o objeto que notificava os ouvintes ou seus colegas.
Geralmente, existem duas convenções.
Um é obter o objeto diretamente do objeto de evento. Você pode fazer isso com getSource (). Mas então você só conseguiria o widget que o fez.
Outra opção é que a classe do ouvinte possa acessar os widgets. Uma maneira é usar classes internas não estáticas (depende de como você o declara); nesse caso, é permitido acessar os membros da classe que contém.
No entanto, neste caso, seus widgets são variáveis, não membros (você tem certeza de que deseja fazer isso?). Portanto, sua única solução seria que os membros os mantenham na classe Listner e, em vez de criar o ouvinte na chamada addlistener, criar um ouvinte, passar os widgets relevantes e adicionar o ouvinte. O ouvinte agora pode acessar esses widgets através de suas próprias referências a eles que são armazenados nos membros.