메서드 호출 후 클래스 변수가 업데이트되지 않음
저는 Java를 처음 접했고 많은 답변을 조사하고 검색하고 읽은 후에야 이것을 게시하고 있습니다. 나는 좀 길을 잃었다. 약간의 안내가 큰 도움이 될 것입니다. 다음은 "ActionListener"인터페이스를 구현하는 클래스의 메소드입니다. 내가하려는 것은 이것입니다. 하나를 클릭하면 두 개의 라디오 버튼 형태로 두 가지 옵션이있는 새 창을 열 수있는 버튼이 있습니다. 내 코드에서 나중에 사용하기 위해 선택된 라디오 버튼을 알아야합니다. "scoreOption"변수를 클래스 변수 및 정적로 선언 한 다음 "actionPerformed"추상 메서드에서 업데이트를 시도합니다. 그러나 그것을 참조하면 (메서드 호출 후) 값은 동일하게 유지됩니다-null 또는 처음에 설정 한 값. 다음은 코드입니다.
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();
}
});
}
});
}
메소드 스코어링 시스템이 호출되는 메인 게임 클래스.
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);
}
}
또한 다음 질문에 대해 알려주세요.
- 다른 "ActionListener"내에서 "ActionListener"를 구현하는 것이 좋습니다. 좋은 연습?
- "actionPerformed"메소드의 선언이 하나만있을 수 있습니까? 아니면 오버로드 될 수도 있습니까?
- "actionPerformed"메서드에서 반환 값을 얻을 수 있습니까?
힌트를 좀 제공해 주시면 정말 감사하겠습니다. 나는 정말 많이 시도한 다음 여기에 게시했습니다. 미리 감사드립니다.
작은 편집 : 내가 "System.out.println" "actioncommand"자체가 콘솔에 인쇄되면 완벽하게 작동합니다. 그러나 클래스 변수를 업데이트하고 메서드 호출 후에 인쇄하려고 할 때가 아닙니다. 이것이 도움이된다면 Dunno.
답변
JFrame은 모달이 아닙니다. 생성하고 표시하면 코드 흐름을 차단하지 않으므로 JFrame이 표시되고 사용자가 변경할 기회가 있기 전에 scoreOption 권한의 값을 추출 합니다. 모달 대화 상자로 생성 된 JDialog와 같은 모달 대화 상자를 사용하거나 JOptionPane (실제로는 후드 아래의 모달 JDialog입니다)을 사용해야합니다. 이렇게하면 코드 흐름이 차단되어 사용자가 데이터를 변경 한 후에 만 데이터를 추출 할 수 있습니다.
요점을 증명하는 예 :
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());
}
}
코드를 실행하면 하위 JFrame을 표시 할 때 대화 상자가 처리 되기 전에 테스트 텍스트가 콘솔에 즉시 표시됩니다 . 버튼을 눌러 대화 상자를 표시하면 버튼을 눌렀을 때까지 테스트 텍스트 표시가 지연되어 텍스트가 변경됩니다.
프레임 버튼을 두 번 누르면 텍스트가 처음 표시 될 때 설정되었으므로 마지막으로 올바른 텍스트가 표시됩니다.
JDialig는 JFrame과 같습니다. 그것은 당신이 어떤 프레임과 같이 구성 요소를 추가하는 것입니다.
차이점은 JDialog 모달을 만들 수 있다는 것입니다. 이것은 다음을 사용할 때 의미합니다.
dialog.setVisible(true);
System.out.println("here");
setVisible (...) 문 뒤의 코드는 대화 상자를 닫을 때까지 실행되지 않습니다. 또한 대화 상자가 닫힐 때까지 부모 JFrame을 클릭 할 수 없음을 의미합니다.
를 만드는 쉬운 방법 modal JDialog
은 JOptionPane
. 사용자 입력에 대한 프롬프트를 쉽게 만드는 몇 가지 미리 정의 된 방법이 있습니다.
예를 들어 귀하의 경우 다음과 같이 할 수 있습니다.
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() );
}
}
위는 "MRE"의 예이기도합니다. 코드는 간단하며 복사 / 붙여 넣기 / 컴파일 및 테스트 할 수있는 단일 클래스에 포함되어 있습니다.
.NET Framework 사용에 대한 더 많은 예제는 대화 상자 사용 방법 에 대한 스윙 자습서의 섹션 을 참조 하십시오JOptionPane
.
라디오 버튼을 정말로 사용하려면 라디오 버튼이있는 패널을 만들고 showConfirmDialog(...)
방법을 사용하여 옵션 창에 표시 할 수 있습니다 . 대화 상자가 닫히면 .NET Framework에서 작업 명령을 가져와야 ButtonModel
합니다 ButtonGroup
.
시작하기위한이 접근 방식의 기본 예제는 JOptionPane의 레이아웃을 설정 및 관리하는 방법을 참조하십시오 .