J'ai eu deux erreurs après avoir compilé mon code.
Les erreurs sont:
1.
local variable input is accessed within inner class;
needs to be declared final
String name = input.getText();
2.
local variable c_age is accessed within inner class;
needs to be declared final
Object child_age = c_age.getSelectedItem();
Voici mon code:
import javax.swing.*;
import Java.awt.event.*;
public class GUI
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Try GUI");
JLabel l1 = new JLabel("Please Enter Your Child's Name");
JTextField input = new JTextField("",10);
JLabel l2 = new JLabel("Choose Your Child's Age");
String[] age = {"Age","1","2","3","4","5","6"};
JComboBox c_age = new JComboBox(age);
JButton button = new JButton("Search");
JTextArea result = new JTextArea();
JScrollPane extend_area = new JScrollPane(result);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
String name = input.getText();
Object child_age = c_age.getSelectedItem();
}
});
JPanel panel = new JPanel();
panel.add(l1);
panel.add(input);
panel.add(l2);
panel.add(c_age);
panel.add(button);
panel.add(extend_area);
frame.add(panel);
frame.setSize(350,350);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Comment puis-je résoudre cette erreur?
Vous devez déclarer
JTextField input = new JTextField("",10);
et
JComboBox c_age = new JComboBox(age);
comme ça:
final JTextField input = new JTextField("",10);
final JComboBox c_age = new JComboBox(age);
Cela signifie que input
et c_age
ne peut pas changer:
Toute variable locale, utilisée mais non déclarée dans une classe interne doit être définitivement affectée avant le corps de la classe interne.
Explication tirée de la Java, Section - 8.1.3 Classes internes et instances de clôture
Si vous déclarez les variables en tant que final, cela résoudra vos erreurs, mais selon moi, ce n'est pas la bonne solution au problème. Un problème similaire a été discuté ici, vous pouvez jeter un œil ici pour plus de compréhension.
Pour résoudre votre problème, vous pouvez définir des méthodes en les utilisant, vous pouvez obtenir une meilleure solution. Pour obtenir un indice, vous pouvez lire Comment accéder à la variable locale non finale à l'intérieur d'une classe interne anonyme
Toute variable que vous utilisez dans la méthode actionPerformed
de votre classe interne devra être déclarée finale. Essayez ce qui suit:
import javax.swing.*;
import Java.awt.event.*;
public class GUI
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Try GUI");
JLabel l1 = new JLabel("Please Enter Your Child's Name");
final JTextField input = new JTextField("",10);
JLabel l2 = new JLabel("Choose Your Child's Age");
String[] age = {"Age","1","2","3","4","5","6"};
final JComboBox c_age = new JComboBox(age);
JButton button = new JButton("Search");
JTextArea result = new JTextArea();
JScrollPane extend_area = new JScrollPane(result);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
String name = input.getText();
Object child_age = c_age.getSelectedItem();
}
});
JPanel panel = new JPanel();
panel.add(l1);
panel.add(input);
panel.add(l2);
panel.add(c_age);
panel.add(button);
panel.add(extend_area);
frame.add(panel);
frame.setSize(350,350);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Comme l'ajout de final
enlève beaucoup de flexibilité, je voudrais suggérer ce qui suit: créer une méthode d'accesseur, ce qui est encouragé de toute façon. Mais cela est surtout utile lorsque vous traitez des objets, alors que dans votre cas, tout est statique. Par conséquent, cette réponse peut ne pas s'appliquer à votre situation spécifique, mais comme la recherche de votre message d'erreur sur Google renvoie cette question comme résultat supérieur, je pense qu'une alternative qui est applicable dans la plupart des cas (l'utilisation d'objets est plus courante que de tout faire à partir d'une méthode statique) devrait également être présent ici.
public class MyClass extends MySuperClass {
private MyPropertyClass aProperty;
public MyClass() {
new JButton().setActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// aProperty.aMethod(); -- Bang! That should be final, the compiler says.
getMyProperty().aMethod(); // -- Everything okay, works fine, no compiler complaints.
}
});
}
public getMyProperty() {
return aProperty;
}
}
L'entrée nommée JTextField a été déclarée à l'intérieur de la méthode principale. Vous devriez probablement faire quelque chose comme ça:
public class GUI{
//declare all your components here e.g.
JTextField input;
public static void main(String args[]){
new GUI();
}
public GUI(){
//instantiate components here
input = new JTextField();
//and so on.
}
}
De cette façon, la référence à l'entrée dans la classe interne ne posera aucun problème.
Vous devez déclarer final
les deux variables auxquelles vous accédez: input
et c_age
.
Si vous ne voulez pas faire cela, vous pouvez soit créer une nouvelle classe appropriée (pas une classe ad-hoc) et les passer en tant que paramètres dans le constructeur, ou (je l'ai fait lorsque je travaillais avec des GUI en Java) créer un classe d'écoute qui prend des objets dans son constructeur et les rend disponibles localement, puis instancie cela de manière ad hoc.
La variable d'entrée et la variable c_age disparaissent une fois l'exécution de la méthode terminée. Vous ne serez pas autorisé à utiliser ces variables à l'intérieur des classes internes locales, sauf si elles sont finales.
Je viens de créer un var temporaire dans la classe principale, par exemple 'tempString', puis il peut être défini sur le var qui cause le problème. Alors:
tempString = myString
de cette façon, je peux appeler tempString sans aucun problème. Consultez mon exemple ci-dessous:
// Create my temp var here
private String tempUrl;
// my function here
public void updatePage(String url)
{
// Can use 'url' here because it's not within inner class
if(!url.equals(""))
{
// Set 'tempUrl' to 'url' so I can use it without problem
tempUrl = url;
// My inner class that used to cause the problem
backgroundUpdate = new Thread(new Runnable()
{
// From here on I use 'tempUrl' to solve the problem
public void run()
{
// Do something with 'tempUrl' here (where 'url' used to be used)
}
});
backgroundUpdate.start();
}
}