在 ActionListener 外部访问 JButton ActionListener 内部所做的更改
Accessing changes made inside JButton ActionListener outside the ActionListener
我会稍微解释一下我的代码:
我有一个包含项目列表的 JComboBox
当按下 JButton "Select" 时,它会注册 JComboBox 中最后一个选定项目的最后一个索引。
现在我需要在主目录中访问这个索引。
这是我的代码:
public static final JComboBox c = new JComboBox();
private static final JButton btnNewButton = new JButton("Select");
而 JButton ActionListener 是:
btnNewButton.addActionListener(新的 ActionListener() {
public void actionPerformed(ActionEvent e)
{
ind = c.getSelectedIndex();
frame.setVisible(false);
}
});
所以按下按钮后,框架关闭
但是现在当我尝试通过
访问 main 中的这个 ind 时
public static void main(String[] args) {
System.out.println(ind);}
我得到一个 return 值 ind = 0
我理解这是因为已经初始化为0了
static ind = 0
但是我如何在 JButton ActionListener 之外访问这个索引?
我需要在我的代码中进一步使用这个索引。
编辑
这是我的 MCVE
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SpringLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.UIManager;
public class MinimalExProgram
{
private static String[] description = { "One", "Two", "Three"};
static int ind;
public static final JComboBox c = new JComboBox(description);
private static final JButton btnNewButton = new JButton("Select");
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().setForeground(UIManager.getColor("ComboBox.disabledBackground"));
frame.getContentPane().setBackground(UIManager.getColor("EditorPane.disabledBackground"));
SpringLayout springLayout = new SpringLayout();
springLayout.putConstraint(SpringLayout.NORTH, btnNewButton, 5, SpringLayout.NORTH, frame.getContentPane());
springLayout.putConstraint(SpringLayout.EAST, c, -6, SpringLayout.WEST, btnNewButton);
springLayout.putConstraint(SpringLayout.EAST, btnNewButton, -10, SpringLayout.EAST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.WEST, c, 6, SpringLayout.WEST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.NORTH, c, 6, SpringLayout.NORTH, frame.getContentPane());
frame.getContentPane().setLayout(springLayout);
frame.setSize(500, 150);
frame.setLocation(400, 200);
frame.setResizable(false);
c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
System.out.print("What I want:");
ind = c.getSelectedIndex();
System.out.println(ind);
frame.setVisible(false);
}
});
frame.getContentPane().add(c);
btnNewButton.setForeground(UIManager.getColor("ComboBox.buttonDarkShadow"));
btnNewButton.setBackground(UIManager.getColor("EditorPane.disabledBackground "));
frame.getContentPane().add(btnNewButton);
frame.setVisible(true);
System.out.print("What I get: ");
System.out.println(ind);
}
}
我需要像之前提到的那样访问 main 里面的 ind
在这里,当我打印出 ind 时,无论我在组合框中做出什么选择,我都会得到零。
好吧,我猜是因为你还没有向我们展示足够的信息来做更多的事情,但我假设:
- 您正在显示第二个 window 作为主要 window
的对话
- 第二个 window 是一个 JFrame 并包含您的 JComboBox 和按钮
- 你要让它在按下按钮时不可见,
- 您尝试从组合框中获取信息,但它始终为 0
- 这可能是因为您在用户有机会与第二个window互动之前获得了信息。
如果是这样,解决方案是使第二个window成为模态对话框window,例如模态 JDialog 而不是 JFrame。这样,调用代码将准确知道第二个 window 何时不再可见,因为调用代码的代码流将被阻塞,直到第二个 window 不再可见。
编辑
概念验证:更改您的代码:
final JFrame frame = new JFrame();
至:
// rename frame variable to dialog for clarity
final JDialog dialog = new JDialog();
dialog.setModalityType(ModalityType.APPLICATION_MODAL);
而且有效。
但是,我还是要去掉不必要的静态变量,不要在 main 方法中做太多代码。例如,...
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
@SuppressWarnings("serial")
public class MinimalExProgram3 extends JPanel {
private static void createAndShowGui() {
MainPanel mainPanel = new MainPanel();
JFrame frame = new JFrame("MinimalExProgram3");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class MainPanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private JTextField field = new JTextField(8);
private ComboPanel comboPanel = new ComboPanel();
JDialog dialog = null;
public MainPanel() {
field.setFocusable(false);
add(field);
add(new JButton(new ShowComboAction("Show Combo")));
}
@Override // make it bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class ShowComboAction extends AbstractAction {
public ShowComboAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
Window mainWin = SwingUtilities.getWindowAncestor(MainPanel.this);
if (dialog == null) {
dialog = new JDialog(mainWin, "Dialog", ModalityType.APPLICATION_MODAL);
dialog.add(comboPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
dialog.setVisible(true);
// code called here after dialog no longer visible
String text = comboPanel.getText();
field.setText(text);
}
}
}
@SuppressWarnings("serial")
class ComboPanel extends JPanel {
private static final String[] DESCRIPTION = { "One", "Two", "Three" };
private int ind;
private JComboBox<String> combo = new JComboBox<>(DESCRIPTION);
private String text;
private SelectionAction selectionAction = new SelectionAction("Select");
private JButton selectionButton = new JButton(selectionAction);
public ComboPanel() {
add(combo);
add(selectionButton);
combo.setAction(selectionAction);
}
public int getInd() {
return ind;
}
public String getText() {
return text;
}
private class SelectionAction extends AbstractAction {
public SelectionAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
ind = combo.getSelectedIndex();
if (ind >= 0) {
text = combo.getSelectedItem().toString();
}
Window win = SwingUtilities.getWindowAncestor(ComboPanel.this);
win.dispose();
}
}
}
我会稍微解释一下我的代码:
我有一个包含项目列表的 JComboBox 当按下 JButton "Select" 时,它会注册 JComboBox 中最后一个选定项目的最后一个索引。
现在我需要在主目录中访问这个索引。
这是我的代码:
public static final JComboBox c = new JComboBox();
private static final JButton btnNewButton = new JButton("Select");
而 JButton ActionListener 是:
btnNewButton.addActionListener(新的 ActionListener() {
public void actionPerformed(ActionEvent e)
{
ind = c.getSelectedIndex();
frame.setVisible(false);
}
});
所以按下按钮后,框架关闭
但是现在当我尝试通过
访问 main 中的这个 ind 时public static void main(String[] args) {
System.out.println(ind);}
我得到一个 return 值 ind = 0
我理解这是因为已经初始化为0了
static ind = 0
但是我如何在 JButton ActionListener 之外访问这个索引?
我需要在我的代码中进一步使用这个索引。
编辑
这是我的 MCVE
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SpringLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.UIManager;
public class MinimalExProgram
{
private static String[] description = { "One", "Two", "Three"};
static int ind;
public static final JComboBox c = new JComboBox(description);
private static final JButton btnNewButton = new JButton("Select");
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().setForeground(UIManager.getColor("ComboBox.disabledBackground"));
frame.getContentPane().setBackground(UIManager.getColor("EditorPane.disabledBackground"));
SpringLayout springLayout = new SpringLayout();
springLayout.putConstraint(SpringLayout.NORTH, btnNewButton, 5, SpringLayout.NORTH, frame.getContentPane());
springLayout.putConstraint(SpringLayout.EAST, c, -6, SpringLayout.WEST, btnNewButton);
springLayout.putConstraint(SpringLayout.EAST, btnNewButton, -10, SpringLayout.EAST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.WEST, c, 6, SpringLayout.WEST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.NORTH, c, 6, SpringLayout.NORTH, frame.getContentPane());
frame.getContentPane().setLayout(springLayout);
frame.setSize(500, 150);
frame.setLocation(400, 200);
frame.setResizable(false);
c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
System.out.print("What I want:");
ind = c.getSelectedIndex();
System.out.println(ind);
frame.setVisible(false);
}
});
frame.getContentPane().add(c);
btnNewButton.setForeground(UIManager.getColor("ComboBox.buttonDarkShadow"));
btnNewButton.setBackground(UIManager.getColor("EditorPane.disabledBackground "));
frame.getContentPane().add(btnNewButton);
frame.setVisible(true);
System.out.print("What I get: ");
System.out.println(ind);
}
}
我需要像之前提到的那样访问 main 里面的 ind 在这里,当我打印出 ind 时,无论我在组合框中做出什么选择,我都会得到零。
好吧,我猜是因为你还没有向我们展示足够的信息来做更多的事情,但我假设:
- 您正在显示第二个 window 作为主要 window 的对话
- 第二个 window 是一个 JFrame 并包含您的 JComboBox 和按钮
- 你要让它在按下按钮时不可见,
- 您尝试从组合框中获取信息,但它始终为 0
- 这可能是因为您在用户有机会与第二个window互动之前获得了信息。
如果是这样,解决方案是使第二个window成为模态对话框window,例如模态 JDialog 而不是 JFrame。这样,调用代码将准确知道第二个 window 何时不再可见,因为调用代码的代码流将被阻塞,直到第二个 window 不再可见。
编辑
概念验证:更改您的代码:
final JFrame frame = new JFrame();
至:
// rename frame variable to dialog for clarity
final JDialog dialog = new JDialog();
dialog.setModalityType(ModalityType.APPLICATION_MODAL);
而且有效。
但是,我还是要去掉不必要的静态变量,不要在 main 方法中做太多代码。例如,...
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
@SuppressWarnings("serial")
public class MinimalExProgram3 extends JPanel {
private static void createAndShowGui() {
MainPanel mainPanel = new MainPanel();
JFrame frame = new JFrame("MinimalExProgram3");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class MainPanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private JTextField field = new JTextField(8);
private ComboPanel comboPanel = new ComboPanel();
JDialog dialog = null;
public MainPanel() {
field.setFocusable(false);
add(field);
add(new JButton(new ShowComboAction("Show Combo")));
}
@Override // make it bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class ShowComboAction extends AbstractAction {
public ShowComboAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
Window mainWin = SwingUtilities.getWindowAncestor(MainPanel.this);
if (dialog == null) {
dialog = new JDialog(mainWin, "Dialog", ModalityType.APPLICATION_MODAL);
dialog.add(comboPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
dialog.setVisible(true);
// code called here after dialog no longer visible
String text = comboPanel.getText();
field.setText(text);
}
}
}
@SuppressWarnings("serial")
class ComboPanel extends JPanel {
private static final String[] DESCRIPTION = { "One", "Two", "Three" };
private int ind;
private JComboBox<String> combo = new JComboBox<>(DESCRIPTION);
private String text;
private SelectionAction selectionAction = new SelectionAction("Select");
private JButton selectionButton = new JButton(selectionAction);
public ComboPanel() {
add(combo);
add(selectionButton);
combo.setAction(selectionAction);
}
public int getInd() {
return ind;
}
public String getText() {
return text;
}
private class SelectionAction extends AbstractAction {
public SelectionAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
ind = combo.getSelectedIndex();
if (ind >= 0) {
text = combo.getSelectedItem().toString();
}
Window win = SwingUtilities.getWindowAncestor(ComboPanel.this);
win.dispose();
}
}
}