variable de classe ne se mettant pas à jour après l'appel de méthode
Je suis assez nouveau sur Java et ce n'est qu'après avoir recherché, cherché sur Google et lu de nombreuses réponses que je publie ceci. Je suis un peu perdu. Un peu d'orientation serait d'une grande aide. Voici une méthode d'une classe qui implémente l'interface "ActionListener". Voici ce que j'essaye de faire: il y a un bouton sur lequel on a cliqué pour ouvrir une nouvelle fenêtre avec deux options sous la forme de deux boutons radio. J'ai besoin de connaître le bouton radio qui a été sélectionné pour une utilisation ultérieure dans mon code. J'ai déclaré la variable "scoreOption" comme variable de classe et statique, puis j'ai tenté de la mettre à jour dans la méthode abstraite "actionPerformed". Mais quand j'y fais référence (après l'appel de la méthode), la valeur reste la même - null, ou ce que je lui ai défini initialement. Voici le code:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class StartEvents implements ActionListener {
StartPanel startingPanel;
static String scoreOption;
public StartEvents(StartPanel startPanel) {
startingPanel = startPanel;
}
// Scoring System Window - 1
public void scoringSystem() {
startingPanel.scoringSystem.addActionListener(new ActionListener () {
@Override
public void actionPerformed(ActionEvent e) {
Panel scoringSystemPanel = new Panel();
JFrame scoreSystemFrame = scoringSystemPanel.frame(150, 250, "Scoring System", 2, true);
JPanel scoreSystemPanel = scoringSystemPanel.panel(Color.lightGray);
JButton confirmSelection = scoringSystemPanel.button(40, 20, "Confirm");
JRadioButton scoreSystem1 = scoringSystemPanel.radioButton("Option 1: Same Points Per Hit");
scoreSystem1.setActionCommand("Option 1");
JRadioButton scoreSystem2 = scoringSystemPanel.radioButton("Option 2: Unique Points Per Hit");
scoreSystem2.setActionCommand("Option 2");
ButtonGroup scoreSys = new ButtonGroup();
scoreSys.add(scoreSystem1);
scoreSys.add(scoreSystem2);
scoreSystemFrame.getContentPane().add(scoreSystemPanel);
scoreSystemPanel.add(scoreSystem1);
scoreSystemPanel.add(scoreSystem2);
scoreSystemPanel.add(confirmSelection);
// Get Selection Event
// Option 1
scoreSystem1.addActionListener(new ActionListener () {
@Override
public void actionPerformed(ActionEvent e) {
if (scoreSystem1.isSelected()) {
scoreOption = scoreSystem1.getActionCommand();
}
}
});
// Option 2
scoreSystem2.addActionListener(new ActionListener () {
@Override
public void actionPerformed(ActionEvent e) {
if (scoreSystem2.isSelected()) {
scoreOption = scoreSystem2.getActionCommand();
}
}
});
// Confirm Event
confirmSelection.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
scoreSystemFrame.dispose();
}
});
}
});
}
Classe de jeu principale où la méthode scoringsystem est appelée.
import java.util.ArrayList;
public class Game {
public static void main(String[] args) {
StartPanel startingPanel = new StartPanel();
startingPanel.makeStartPanel();
StartEvents starter = new StartEvents(startingPanel);
starter.rulesButton();
starter.exitButton();
starter.highScoresButton();
ArrayList<Integer> dimensions = starter.boardSizeSelector();
// Problem Zone
System.out.println(StartEvents.scoreOption);
starter.scoringSystem();
System.out.println(StartEvents.scoreOption);
// The two values of scoreOption should be different
String[] playPanelDetails = {"970", "Player 1", "450"};
// Final Start of the Game
starter.startGameButton(playPanelDetails, dimensions);
}
}
De plus, pourriez-vous me faire part des questions suivantes:
- Il est recommandé de mettre en œuvre "ActionListener" dans un autre "ActionListener"? Bonnes pratiques?
- Ne peut-il y avoir qu'une seule déclaration de la méthode "actionPerformed" ou peut-elle aussi être surchargée?
- Est-il possible d'obtenir une valeur de retour de la méthode "actionPerformed"?
Je serais vraiment reconnaissant si même quelques indices pouvaient être fournis. J'ai vraiment beaucoup essayé et je l'ai seulement posté ici. Merci beaucoup d'avance.
Petite édition: Quand je "System.out.println" la "commande d'action" là-bas, cela fonctionne parfaitement, en imprimant dans la console. Mais pas lorsque j'essaie de mettre à jour la variable de classe, puis de l'imprimer après l'appel de la méthode. Je ne sais pas si cela aide.
Réponses
Les JFrames ne sont pas modaux - vous en créez un et l'affichez, cela ne bloque pas le flux de code, et vous extrayez donc la valeur de scoreOption dès que le JFrame est affiché et avant que l'utilisateur n'ait eu la possibilité de le changer. Vous devez utiliser un dialogue modal tel qu'un JDialog qui est créé comme un dialogue modal ou utiliser un JOptionPane (qui n'est en fait qu'un JDialog modal sous le capot). Cela bloquera le flux de code afin que vous extrayiez les données uniquement après qu'elles aient été modifiées par l'utilisateur.
Un exemple qui prouve le point:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FooGui01 extends JPanel {
private String frameTest = "";
private String dialogTest = "";
private JFrame mainFrame = new JFrame("Main GUI");
private JFrame subFrame;
private JDialog dialog;
public FooGui01() {
JButton showFrameBtn = new JButton("Show JFrame");
showFrameBtn.addActionListener(e -> {
changeTest1WithJFrame();
System.out.println("frameTest: " + frameTest);
});
JButton showDialogBtn = new JButton("Show JDialog");
showDialogBtn.addActionListener(e -> {
changeTest2WithModalDialog();
System.out.println("dialogTest: " + dialogTest);
});
JPanel panel = new JPanel();
panel.add(showDialogBtn);
panel.add(showFrameBtn);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(panel);
mainFrame.pack();
mainFrame.setLocationByPlatform(true);
mainFrame.setVisible(true);
}
public void changeTest1WithJFrame() {
if (subFrame == null) {
subFrame = new JFrame("Frame");
JButton button = new JButton("Press me");
button.addActionListener(e -> {
frameTest = "Hello World and frameTest";
subFrame.setVisible(false);
});
JPanel panel = new JPanel();
panel.add(button);
subFrame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
subFrame.add(panel);
subFrame.pack();
subFrame.setLocationByPlatform(true);
}
subFrame.setVisible(true);
}
public void changeTest2WithModalDialog() {
if (dialog == null) {
dialog = new JDialog(mainFrame, "Dialog", Dialog.ModalityType.APPLICATION_MODAL);
JButton button = new JButton("Press me");
button.addActionListener(e -> {
dialogTest = "Hello World and dialogTest";
dialog.setVisible(false);
});
JPanel panel = new JPanel();
panel.add(button);
dialog.add(panel);
dialog.pack();
dialog.setLocationByPlatform(true);
}
dialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new FooGui01());
}
}
Si vous exécutez le code, lorsque vous affichez le sous-JFrame, le texte de test s'affiche immédiatement dans la console avant que la boîte de dialogue n'ait été traitée. Si vous appuyez sur le bouton pour afficher la boîte de dialogue, l'affichage du texte de test est retardé jusqu'à ce que le bouton ait été enfoncé, ce qui change le texte.
Le fait d'appuyer deux fois sur le bouton de cadre affichera finalement le texte correct puisque le texte a été défini lors de la première utilisation.
Un JDialig est comme un JFrame. C'est-à-dire que vous y ajoutez des composants comme vous le faites pour n'importe quel cadre.
La différence est que vous pouvez créer un modal JDialog. Cela signifie que lorsque vous utilisez:
dialog.setVisible(true);
System.out.println("here");
Le code après l'instruction setVisible (...) ne sera pas exécuté tant que la boîte de dialogue ne sera pas fermée. Cela signifie également que vous ne pouvez pas cliquer sur le JFrame parent tant que la boîte de dialogue n'est pas fermée.
Un moyen simple de créer un fichier modal JDialog
est d'utiliser un fichier JOptionPane
. Il possède des méthodes prédéfinies qui facilitent l'invitation à saisir l'utilisateur.
Par exemple, dans votre cas, vous pouvez faire quelque chose comme:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SSCCE extends JPanel
{
private int scoringOption = -1;
public SSCCE()
{
JButton button = new JButton("Change Points Option");
add(button);
button.addActionListener((e) -> displayOptionDialog());
}
private void displayOptionDialog()
{
Window window = SwingUtilities.windowForComponent( this );
// Custom button text
Object[] options = {"Option 1: Same Points Per Hit", "Option 2: Unique Points Per Hit"};
scoringOption = JOptionPane.showOptionDialog(
window,
"Select your scoring option:",
"Scoring Option",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
null);
System.out.println( scoringOption );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
Ce qui précède est également un exemple de «MRE». Le code est simple et contenu dans une seule classe que vous pouvez copier / coller / compiler et tester.
Lisez la section du didacticiel Swing sur l' utilisation des boîtes de dialogue pour plus d'exemples d'utilisation d'un fichier JOptionPane
.
Si vous souhaitez vraiment utiliser des boutons radio, vous pouvez créer un panneau avec les boutons radio et les afficher dans le panneau d'options à l'aide de la showConfirmDialog(...)
méthode. Lorsque la boîte de dialogue se ferme, vous devez alors obtenir la commande d'action ButtonModel
du ButtonGroup
.
Voir: comment définir et gérer la disposition de JOptionPane pour un exemple de base de cette approche pour vous aider à démarrer.